diff --git a/.github/vcpkg_triplets/x64-windows-static.cmake b/.github/vcpkg_triplets/x64-windows-static.cmake new file mode 100644 index 0000000000000..66655f1877714 --- /dev/null +++ b/.github/vcpkg_triplets/x64-windows-static.cmake @@ -0,0 +1,5 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE static) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_BUILD_TYPE release) diff --git a/.github/vcpkg_triplets/x64-windows.cmake b/.github/vcpkg_triplets/x64-windows.cmake new file mode 100644 index 0000000000000..1ae9006118fb3 --- /dev/null +++ b/.github/vcpkg_triplets/x64-windows.cmake @@ -0,0 +1,5 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE dynamic) + +set(VCPKG_BUILD_TYPE release) diff --git a/.github/workflows/msvc-full-features.yml b/.github/workflows/msvc-full-features.yml new file mode 100644 index 0000000000000..6758ca01ed785 --- /dev/null +++ b/.github/workflows/msvc-full-features.yml @@ -0,0 +1,91 @@ +name: Cataclysm Windows build + +on: + push: + branches: + - master + paths-ignore: + - 'android/**' + - 'build-data/osx/**' + - 'doc/**' + - 'doxygen_doc/**' + - 'lgtm/**' + - 'msvc-object_creator/**' + - 'tools/**' + - 'utilities/**' + pull_request: + branches: + - master + paths-ignore: + - 'android/**' + - 'build-data/osx/**' + - 'doc/**' + - 'doxygen_doc/**' + - 'lgtm/**' + - 'msvc-object_creator/**' + - 'tools/**' + - 'utilities/**' + +env: + # There's not enough disk space to build both release and debug versions of + # our dependencies, so we hack the triplet file to build only release versions + # Have to use github.workspace because runner namespace isn't available yet. + VCPKG_OVERLAY_TRIPLETS: ${{ github.workspace }}\.github\vcpkg_triplets + +jobs: + build_catatclysm: + name: Build + runs-on: windows-2019 + + steps: + - name: checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.0.2 + + - name: Restore artifacts, or run vcpkg, build and cache artifacts + uses: lukka/run-vcpkg@main + id: runvcpkg + with: + additionalCachedPaths: '${{ runner.workspace }}/Cataclysm-DDA/msvc-full-features/vcpkg_installed' + appendedCacheKey: ${{ hashFiles( 'msvc-full-features/vcpkg.json', '.github/vcpkg_triplets/**' ) }} + setupOnly: true + vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' + # We have to use at least this version of vcpkg to include fixes for yasm-tool's + # availability only as an x86 host tool. Keep it in sync with the builtin-baseline + # field in vcpkg.json. Caching happens as a post-action which runs at the end of + # the whole workflow, after vcpkg install happens during msbuild run. + vcpkgGitCommitId: '49b67d9cb856424ff69f10e7721aec5299624268' + + - name: Integrate vcpkg + run: | + vcpkg integrate install + + - name: Build + run: | + cd msvc-full-features + msbuild -m -p:Configuration=Release -p:Platform=x64 -target:Cataclysm-vcpkg-static Cataclysm-vcpkg-static.sln + + - name: Dump logs if build failed + if: failure() + run: | + echo ================================================= + Get-ChildItem "${{ runner.workspace }}/Cataclysm-DDA/msvc-full-features/vcpkg_installed" -Recurse + echo ================================================= + Get-ChildItem "${{ runner.workspace }}/b/vcpkg/buildtrees" | + Foreach-Object { + Get-ChildItem $_.FullName -Filter *.log | + Foreach-Object { + echo ================================================= + echo $_.FullName + echo ================================================= + type $_.FullName + } + } + + - name: Clean + run: | + Get-ChildItem -Path Cataclysm-lib-vcpkg-static-Release-x64.* | Foreach-Object { rm $_.FullName } diff --git a/.github/workflows/object_creator.yml b/.github/workflows/object_creator.yml new file mode 100644 index 0000000000000..13d76ff5f919f --- /dev/null +++ b/.github/workflows/object_creator.yml @@ -0,0 +1,91 @@ +name: ObjectCreator Windows build + +on: + push: + branches: + - master + paths-ignore: + - 'android/**' + - 'build-data/osx/**' + - 'doc/**' + - 'doxygen_doc/**' + - 'lgtm/**' + - 'tools/**' + - 'utilities/**' + pull_request: + branches: + - master + paths-ignore: + - 'android/**' + - 'build-data/osx/**' + - 'doc/**' + - 'doxygen_doc/**' + - 'lgtm/**' + - 'tools/**' + - 'utilities/**' + +env: + # There's not enough disk space to build both release and debug versions of + # our dependencies, so we hack the triplet file to build only release versions + # Have to use github.workspace because runner namespace isn't available yet. + VCPKG_OVERLAY_TRIPLETS: ${{ github.workspace }}\.github\vcpkg_triplets + +jobs: + build_object_creator: + name: Build + runs-on: windows-2019 + + steps: + - name: checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.0.2 + + - name: Restore artifacts, or run vcpkg, build and cache artifacts + uses: lukka/run-vcpkg@main + id: runvcpkg + with: + additionalCachedPaths: '${{ runner.workspace }}/Cataclysm-DDA/msvc-full-features/vcpkg_installed;${{ runner.workspace }}/Cataclysm-DDA/msvc-object_creator/vcpkg_installed' + appendedCacheKey: ${{ hashFiles( '$msvc-full-features/vcpkg.json', 'msvc-object_creator/vcpkg.json', '.github/vcpkg_triplets/**' ) }} + setupOnly: true + vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' + # We have to use at least this version of vcpkg to include fixes for yasm-tool's + # availability only as an x86 host tool. Keep it in sync with the builtin-baseline + # field in vcpkg.json. Caching happens as a post-action which runs at the end of + # the whole workflow, after vcpkg install happens during msbuild run. + vcpkgGitCommitId: '49b67d9cb856424ff69f10e7721aec5299624268' + + - name: Integrate vcpkg + run: | + vcpkg integrate install + + - name: Build + run: | + cd msvc-object_creator + msbuild -m -p:Configuration=Release -p:Platform=x64 ObjectCreator-vcpkg-static.sln + + - name: Dump logs if build failed + if: failure() + run: | + echo ================================================= + Get-ChildItem "${{ runner.workspace }}/Cataclysm-DDA/msvc-full-features/vcpkg_installed" -Recurse + echo ================================================= + Get-ChildItem "${{ runner.workspace }}/Cataclysm-DDA/msvc-object_creator/vcpkg_installed" -Recurse + echo ================================================= + Get-ChildItem "${{ runner.workspace }}/b/vcpkg/buildtrees" | + Foreach-Object { + Get-ChildItem $_.FullName -Filter *.log | + Foreach-Object { + echo ================================================= + echo $_.FullName + echo ================================================= + type $_.FullName + } + } + + - name: Clean + run: | + Get-ChildItem -Path Cataclysm-lib-vcpkg-static-Release-x64.*,ObjectCreator-vcpkg-static-Release-x64.* | Foreach-Object { rm $_.FullName } diff --git a/data/json/effects.json b/data/json/effects.json index 2317b34640263..6bfe495a9d7d5 100644 --- a/data/json/effects.json +++ b/data/json/effects.json @@ -632,6 +632,7 @@ "int_add_val": 1, "int_decay_step": -1, "int_decay_tick": 90, + "int_decay_remove": true, "resist_traits": [ "ELFA_NV" ], "base_mods": { "per_mod": [ -3, 0 ] }, "scaling_mods": { "per_mod": [ -2, -1 ] } diff --git a/data/json/items/ammo/nail.json b/data/json/items/ammo/nail.json index a0b82e271a860..9aea0f4238931 100644 --- a/data/json/items/ammo/nail.json +++ b/data/json/items/ammo/nail.json @@ -34,6 +34,6 @@ "range": 3, "damage": { "damage_type": "bullet", "amount": 3, "armor_penetration": 1 }, "dispersion": 180, - "effects": [ "NON_FOULING" ] + "effects": [ "NON_FOULING", "HURT_WHEN_WIELDED" ] } ] diff --git a/data/json/items/comestibles/carnivore.json b/data/json/items/comestibles/carnivore.json index a524d63a527ac..091de3a93c7b3 100644 --- a/data/json/items/comestibles/carnivore.json +++ b/data/json/items/comestibles/carnivore.json @@ -307,6 +307,46 @@ "fun": 0, "flags": [ "EATEN_HOT", "NUTRIENT_OVERRIDE", "BAD_TASTE" ] }, + { + "type": "COMESTIBLE", + "id": "meat_mutant_tainted", + "copy-from": "mutant_meat", + "name": { "str": "chunk of tainted mutant meat", "str_pl": "chunks of tainted mutant meat" }, + "color": "magenta", + "snippet_category": "tainted_mutant_meat_desc", + "looks_like": "meat", + "cooks_like": "meat_mutant_tainted_cooked", + "spoils_in": "4 hours", + "use_action": [ "POISON" ], + "price": 0, + "price_postapoc": 5, + "fun": -15, + "flags": [ "TRADER_AVOID", "SMOKABLE", "BAD_TASTE", "RAW" ], + "smoking_result": "meat_mutant_tainted_smoked" + }, + { + "type": "COMESTIBLE", + "id": "meat_mutant_tainted_cooked", + "copy-from": "meat_mutant_tainted", + "name": { "str": "cooked tainted mutant meat" }, + "snippet_category": "cooked_tainted_mutant_meat_desc", + "looks_like": "meat_cooked", + "parasites": 0, + "proportional": { "price_postapoc": 1.5, "fun": 0.7 }, + "extend": { "flags": [ "EATEN_HOT" ] }, + "delete": { "flags": [ "RAW" ] } + }, + { + "type": "COMESTIBLE", + "id": "meat_mutant_tainted_smoked", + "copy-from": "meat_mutant_tainted_cooked", + "name": { "str": "smoked tainted mutant meat" }, + "description": "Rotten mutatant meat that has been heavily smoked for preservation.", + "spoils_in": "24 days", + "quench": -1, + "proportional": { "price_postapoc": 1.8, "fun": 0.7 }, + "extend": { "flags": [ "EATEN_HOT", "SMOKED" ] } + }, { "type": "COMESTIBLE", "comestible_type": "FOOD", diff --git a/data/json/items/comestibles/other.json b/data/json/items/comestibles/other.json index 318752030b61a..850cdf8fa21f2 100644 --- a/data/json/items/comestibles/other.json +++ b/data/json/items/comestibles/other.json @@ -454,6 +454,7 @@ }, { "type": "COMESTIBLE", + "comestible_type": "FOOD", "id": "soybean", "name": { "str_sp": "soybeans" }, "volume": "250 ml", @@ -474,6 +475,7 @@ }, { "type": "COMESTIBLE", + "comestible_type": "FOOD", "id": "raw_edamame", "name": { "str": "raw edamame" }, "volume": "250 ml", diff --git a/data/json/items/fluff.json b/data/json/items/fluff.json index c8727f1f60ebb..a4ef05e53707f 100644 --- a/data/json/items/fluff.json +++ b/data/json/items/fluff.json @@ -268,7 +268,7 @@ "sided": true, "material_thickness": 2, "flags": [ "OVERSIZE", "BELTED", "RESTRICT_HANDS", "WATER_FRIENDLY" ], - "armor": [ { "coverage": 10, "covers": [ "arm_l", "arm_r", "hand_l", "hand_r" ] } ] + "armor": [ { "encumbrance": 45, "coverage": 10, "covers": [ "arm_l", "arm_r", "hand_l", "hand_r" ] } ] }, { "type": "GENERIC", diff --git a/data/json/items/generic.json b/data/json/items/generic.json index 3a64d86c0085b..62fd50b18fa36 100644 --- a/data/json/items/generic.json +++ b/data/json/items/generic.json @@ -732,6 +732,7 @@ "material": [ "steel" ], "weight": "302 g", "volume": "500 ml", + "flags": [ "HURT_WHEN_WIELDED" ], "to_hit": -2 }, { @@ -2873,6 +2874,7 @@ "stack_size": 50, "material": [ "steel" ], "symbol": ".", + "flags": [ "HURT_WHEN_WIELDED" ], "color": "white", "ammo_type": "components" }, diff --git a/data/json/items/tool_armor.json b/data/json/items/tool_armor.json index 31820952354e5..a16e499ae83ee 100644 --- a/data/json/items/tool_armor.json +++ b/data/json/items/tool_armor.json @@ -1241,6 +1241,7 @@ "to_hit": 1, "material": [ "plastic" ], "symbol": "[", + "looks_like": "mask_dust", "color": "light_gray", "warmth": 10, "material_thickness": 2, diff --git a/data/json/mapgen/exodii/exo_safehouse.json b/data/json/mapgen/exodii/exo_safehouse.json new file mode 100644 index 0000000000000..10e2c55d271cf --- /dev/null +++ b/data/json/mapgen/exodii/exo_safehouse.json @@ -0,0 +1,144 @@ +[ + { + "om_terrain": "exo_safehouse_stone_0", + "//": "A medieval stone barn from the exodii's most recently visited world, converted to a safehouse for their scouts to hole up in, and transported to our world during the portal storms.", + "type": "mapgen", + "weight": 100, + "method": "json", + "object": { + "rows": [ + " ......... ", + " ....,,,,,,,.... ", + " ....,,,,,,,,,,,,,.. ", + " ..,,,,,,;;;;;,,,,,.. ", + " .,,,;;;;;;;;;;;;;,,.. ", + " ..,,;x;;;;;;;;;x;,,,.. ", + " .,,;x###########x;,,.. ", + "..,,;;#|ccc|ccc|#;;,,,..", + ".,,,;;#_3____{{g#;;;,,..", + ".,,;;;#_|__|{{||#;;;,,..", + ".,,;;;#<---I----#;;;,,..", + ".,,;;;#|------1|#;;;,,..", + ".,,;;;#C--------#;;;,,..", + ".,,;;;#C-----3--#;;;,,..", + ".,,;;;#C--------#;;;,,..", + "..,,;;#||-----||#;;;,,..", + "..,,;;#1-------1#;;,,,..", + " .,,;x####MMM####x;,,.. ", + " .,,;;x;;;;;;;;;x;,,,.. ", + " ..,,;x;;;;;;;;;x;,,,.. ", + " ..,,xxxxx;;xxxx;,,.. ", + " ...,,,,,,,,,,,,,,... ", + " ....,,,,,,,,.... ", + " .......... " + ], + "fill_ter": "t_dirtfloor", + "palettes": [ "exodii_stone_palette" ], + "place_monster": [ + { + "monster": "mon_exodii_quad", + "x": [ 10, 11 ], + "y": [ 19, 22 ], + "pack_size": [ 1, 3 ], + "spawn_data": { + "patrol": [ + { "x": 1, "y": 22 }, + { "x": 1, "y": 1 }, + { "x": 22, "y": 1 }, + { "x": 22, "y": 22 }, + { "x": 11, "y": 22 }, + { "x": 12, "y": 20 } + ] + } + }, + { + "monster": "mon_exodii_quad", + "x": 11, + "y": 12, + "spawn_data": { "patrol": [ { "x": 12, "y": 16 }, { "x": 7, "y": 10 }, { "x": 12, "y": 13 }, { "x": 8, "y": 12 } ] } + }, + { + "monster": "mon_exodii_worker", + "x": 7, + "y": 8, + "spawn_data": { "patrol": [ { "x": 14, "y": 8 }, { "x": 7, "y": 8 } ] } + } + ], + "furniture": { "Y": "f_scrap_antenna", "I": "f_exodii_lamp" } + } + }, + { + "om_terrain": "exo_safehouse_stone_1", + "type": "mapgen", + "weight": 100, + "method": "json", + "object": { + "fill_ter": "t_junk_floor", + "rows": [ + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvv###########vvvvvvv", + "vvvvvv#<{{{I{{{g#vvvvvvv", + "vvvvvv#'''''{'''#vvvvvvv", + "vvvvvv#'|1'|{1|C#vvvvvvv", + "vvvvvv#>vvvvvvvv#vvvvvvv", + "vvvvvv#vvvvvvvvv#vvvvvvv", + "vvvvvv#vvvvvvvvv#vvvvvvv", + "vvvvvv#vvvvvvvvv#vvvvvvv", + "vvvvvv#vvvvvvvvv#vvvvvvv", + "vvvvvv#vvvvvvvvv#vvvvvvv", + "vvvvvv#vvvvvvvvv#vvvvvvv", + "vvvvvv###########vvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv" + ], + "palettes": [ "exodii_stone_palette" ], + "furniture": { "I": "f_exodii_charger_cheap" } + } + }, + { + "om_terrain": "exo_safehouse_stone_2", + "type": "mapgen", + "weight": 100, + "method": "json", + "object": { + "fill_ter": "t_tile_flat_roof", + "rows": [ + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvv^^^^^^^^^^^vvvvvvv", + "vvvvvv^>{Y^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^{^^^^^^^^vvvvvvv", + "vvvvvv^^I^^^^^^^^vvvvvvv", + "vvvvvv^^^^^^^^^^^vvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv", + "vvvvvvvvvvvvvvvvvvvvvvvv" + ], + "palettes": [ "exodii_stone_palette" ], + "furniture": { "Y": "f_exodii_portal_tower", "I": "f_exodii_scanner" } + } + } +] diff --git a/data/json/mapgen_palettes/exodii/medieval.json b/data/json/mapgen_palettes/exodii/medieval.json new file mode 100644 index 0000000000000..f54de31aa8ccf --- /dev/null +++ b/data/json/mapgen_palettes/exodii/medieval.json @@ -0,0 +1,45 @@ +[ + { + "type": "palette", + "id": "exodii_stone_palette", + "//": "For medieval buildings the exodii have repurposed.", + "terrain": { + " ": [ [ "t_region_groundcover", 500 ], "t_region_tree" ], + ".": "t_glassed_sand", + ",": [ [ "t_glassed_sand", 3 ], "t_sandmound", "t_sand" ], + ";": "t_sand", + "#": "t_drystone_wall", + "_": "t_dirtfloor", + "-": "t_dirt", + "2": "t_dirt", + "5": "t_dirt", + "'": "t_junk_floor", + "<": "t_ladder_up", + ">": "t_ladder_down", + "^": "t_tile_flat_roof", + "|": "t_junk_wall", + "M": "t_door_metal_c", + "v": "t_open_air", + "x": "t_drystone_wall_half", + "4": "t_sand" + }, + "monster": { + "1": { "monster": "mon_exodii_turret" }, + "2": { "monster": "mon_exodii_turret" }, + "3": { "monster": "mon_exodii_worker" }, + "5": { "monster": "mon_exodii_worker" } + }, + "furniture": { + "c": [ "f_metal_crate_r", "f_metal_crate_c" ], + "C": [ "f_metal_crate_r", "f_metal_crate_c" ], + "g": "f_capacitor", + "{": "f_ground_cable", + ".": [ [ "f_null", 2000 ], [ "f_rubble_rock", 100 ] ], + ",": [ [ "f_null", 2000 ], [ "f_rubble_rock", 100 ], [ "f_boulder_small", 12 ], "f_boulder_medium" ] + }, + "items": { + "c": [ { "item": "SUS_exodii_storage_medvalue", "chance": 50 } ], + "C": [ { "item": "SUS_exodii_storage_highvalue", "chance": 50 } ] + } + } +] diff --git a/data/json/monster_factions.json b/data/json/monster_factions.json index 0cfc4c7699ee7..76a163e7980da 100644 --- a/data/json/monster_factions.json +++ b/data/json/monster_factions.json @@ -433,7 +433,8 @@ { "type": "MONSTER_FACTION", "name": "fungus", - "neutral": [ "bot", "fish" ] + "neutral": [ "bot", "fish" ], + "hate": "triffid" }, { "type": "MONSTER_FACTION", @@ -479,7 +480,8 @@ { "type": "MONSTER_FACTION", "name": "triffid", - "base_faction": "plant" + "base_faction": "plant", + "hate": "fungus" }, { "type": "MONSTER_FACTION", diff --git a/data/json/overmap/overmap_special/alien.json b/data/json/overmap/overmap_special/alien.json new file mode 100644 index 0000000000000..14d9c73887d7f --- /dev/null +++ b/data/json/overmap/overmap_special/alien.json @@ -0,0 +1,17 @@ +[ + { + "type": "overmap_special", + "id": "Out-of-place Stone Barn", + "//": "Exodii safehouse built in a medieval stone barn", + "overmaps": [ + { "point": [ 0, 0, 0 ], "overmap": "exo_safehouse_stone_0_north" }, + { "point": [ 0, 0, 1 ], "overmap": "exo_safehouse_stone_1_north" }, + { "point": [ 0, 0, 2 ], "overmap": "exo_safehouse_stone_2_north" } + ], + "locations": [ "forest_without_trail", "land", "wilderness" ], + "city_distance": [ 0, 30 ], + "city_sizes": [ 0, 16 ], + "occurrences": [ 0, 1 ], + "flags": [ "EXODII", "CBM" ] + } +] diff --git a/data/json/overmap/overmap_terrain/overmap_terrain_alien.json b/data/json/overmap/overmap_terrain/overmap_terrain_alien.json index e5178718e09d2..851f53ace44d0 100644 --- a/data/json/overmap/overmap_terrain/overmap_terrain_alien.json +++ b/data/json/overmap/overmap_terrain/overmap_terrain_alien.json @@ -1,4 +1,31 @@ [ + { + "type": "overmap_terrain", + "id": "exo_safehouse_stone_0", + "name": "unusual stone barn", + "sym": "^", + "color": "brown", + "see_cost": 2, + "flags": [ "KNOWN_UP" ] + }, + { + "type": "overmap_terrain", + "id": "exo_safehouse_stone_1", + "name": "unusual stone barn", + "sym": "^", + "color": "brown", + "see_cost": 2, + "flags": [ "KNOWN_UP", "KNOWN_DOWN" ] + }, + { + "type": "overmap_terrain", + "id": "exo_safehouse_stone_2", + "name": "unusual stone barn roof", + "sym": "^", + "color": "brown", + "see_cost": 2, + "flags": [ "KNOWN_DOWN" ] + }, { "type": "overmap_terrain", "id": [ "slimepit_bottom", "slimepit_top" ], diff --git a/data/json/recipes/practice/fabrication.json b/data/json/recipes/practice/fabrication.json index c9d53179588f2..4a04b714d75a0 100644 --- a/data/json/recipes/practice/fabrication.json +++ b/data/json/recipes/practice/fabrication.json @@ -21,5 +21,41 @@ ], "autolearn": [ [ "fabrication", 2 ] ], "book_learn": [ [ "recipe_arrows", 1 ] ] + }, + { + "id": "prac_carving", + "type": "practice", + "activity_level": "LIGHT_EXERCISE", + "category": "CC_PRACTICE", + "subcategory": "CSC_PRACTICE_FABRICATION", + "name": "carving", + "description": "Practice carving different forms and shapes in a piece of wood.", + "skill_used": "fabrication", + "practice_data": { "min_difficulty": 0, "max_difficulty": 1, "skill_limit": 2 }, + "proficiencies": [ { "proficiency": "prof_carving", "fail_multiplier": 1, "time_multiplier": 1 } ], + "time": "1 h", + "qualities": [ { "id": "CUT", "level": 1 } ], + "//": "One could use other wooden items to practice carving, but the stick and plank are the most easily adquired.", + "components": [ [ [ "stick", 1 ], [ "2x4", 1 ] ] ], + "byproducts": [ [ "splinter", 5 ] ], + "autolearn": [ [ "fabrication", 0 ] ] + }, + { + "id": "prac_carpentry_basic", + "type": "practice", + "activity_level": "LIGHT_EXERCISE", + "category": "CC_PRACTICE", + "subcategory": "CSC_PRACTICE_FABRICATION", + "name": "basic carpentry", + "description": "Practice basic carpentry by cutting, shaping and uniting some planks or sticks with nails.", + "skill_used": "fabrication", + "practice_data": { "min_difficulty": 0, "max_difficulty": 1, "skill_limit": 2 }, + "proficiencies": [ { "proficiency": "prof_carpentry_basic", "fail_multiplier": 1, "time_multiplier": 1 } ], + "time": "1 h", + "qualities": [ { "id": "HAMMER", "level": 1 }, { "id": "CUT", "level": 1 } ], + "//": "You destroy the wood with your practice, and the nails are now unusable.", + "components": [ [ [ "stick", 4 ], [ "2x4", 2 ] ], [ [ "nail", 20 ] ] ], + "byproducts": [ [ "splinter", 15 ] ], + "autolearn": [ [ "fabrication", 0 ] ] } ] diff --git a/data/json/recipes/recipe_food.json b/data/json/recipes/recipe_food.json index 9f114184f8c23..0d8022b61c68d 100644 --- a/data/json/recipes/recipe_food.json +++ b/data/json/recipes/recipe_food.json @@ -262,6 +262,18 @@ "proficiencies": [ { "proficiency": "prof_food_prep" } ], "components": [ [ [ "mutant_meat", 1 ] ] ] }, + { + "type": "recipe", + "copy-from": "mutant_meat_cooked", + "result": "meat_mutant_tainted_cooked", + "components": [ [ [ "meat_mutant_tainted", 1 ] ] ] + }, + { + "type": "recipe", + "result": "meat_mutant_tainted_smoked", + "copy-from": "meat_smoked", + "components": [ [ [ "meat_mutant_tainted", 1 ] ] ] + }, { "type": "recipe", "activity_level": "NO_EXERCISE", diff --git a/data/json/snippets/mutant_anatomy.json b/data/json/snippets/mutant_anatomy.json index 23849977383a9..ea89111284cb9 100644 --- a/data/json/snippets/mutant_anatomy.json +++ b/data/json/snippets/mutant_anatomy.json @@ -43,6 +43,50 @@ } ] }, + { + "type": "snippet", + "category": "tainted_mutant_meat_desc", + "text": [ + { + "id": "tainted_mutant_meat_1", + "text": "Poisonous meat from a heavily mutated animal. It has an unsettling loose and spongy texture and a putrid smell. There are strange tangles and formations in it that don't appear natural at all: bits of bone and hair crusted up inside the muscle, as if trying to form another organism. You'd have to be truly desperate to try eating this." + }, + { + "id": "tainted_mutant_meat_2", + "text": "Poisonous meat from a heavily mutated animal. Although it came from muscle tissue, it has a curious swirling grain pattern, and at the center of each grain is a knot of hard, cartilaginous tissue. Its smell is nauseating." + }, + { + "id": "tainted_mutant_meat_3", + "text": "Poisonous meat from a heavily mutated animal. This is from muscle, but in the fascial tissue between the muscles, thick spiny hairs have grown. Foul-smelling, cream-colored fluid gushes out whenever a hair pulls loose." + }, + { + "id": "tainted_mutant_meat_4", + "text": "Poisonous meat from a heavily mutated animal. Although this came from muscle, it has a thick cordlike texture and smells like leather and bread mold." + } + ] + }, + { + "type": "snippet", + "category": "cooked_tainted_mutant_meat_desc", + "text": [ + { + "id": "cooked_tainted_mutant_meat_1", + "text": "This is a cooked chunk of meat from a mutated animal. It has an unsettling, spongy texture, but otherwise tastes… mostly normal. Hopefully you won't vomit while eating this…" + }, + { + "id": "cooked_tainted_mutant_meat_2", + "text": "This is a cooked chunk of meat from a mutated animal. You thought you'd cleared out all the gross parts, but while cooking, a fluid-filled sac inside burst and covered it in some kind of foul-smelling thick grease." + }, + { + "id": "cooked_tainted_mutant_meat_3", + "text": "This is a cooked chunk of meat from a mutated animal. The surface is peppered with divots from the pieces you had to dig out to make it seem edible." + }, + { + "id": "cooked_tainted_mutant_meat_4", + "text": "This is a cooked chunk of meat from a mutated animal. Heat caused the muscles to twist and move as if they were alive, and now it has writhed itself into a dense knot." + } + ] + }, { "type": "snippet", "category": "mutant_brain_desc", diff --git a/data/mods/Magiclysm/harvest.json b/data/mods/Magiclysm/harvest.json index 521c367564aff..c17cb3260eec5 100644 --- a/data/mods/Magiclysm/harvest.json +++ b/data/mods/Magiclysm/harvest.json @@ -346,5 +346,19 @@ { "drop": "sinew", "type": "bone", "mass_ratio": 0.00035 }, { "drop": "bone_demihuman", "type": "bone", "mass_ratio": 0.1 } ] + }, + { + "id": "zombie_owlbear", + "//": "identical to owlbear except ", + "type": "harvest", + "entries": [ + { "drop": "meat_mutant_tainted", "type": "flesh", "mass_ratio": 0.32 }, + { "drop": "owlbear_stone", "scale_num": [ 1, 1 ], "max": 1, "type": "offal" }, + { "drop": "bone_tainted", "type": "bone", "mass_ratio": 0.15 }, + { "drop": "raw_tainted_fur", "type": "skin", "mass_ratio": 0.015 }, + { "drop": "fat_tainted", "type": "flesh", "mass_ratio": 0.07 }, + { "drop": "feather", "type": "skin", "mass_ratio": 0.005 }, + { "drop": "adrenal_gland_large", "type": "bionic", "max": 2 } + ] } ] diff --git a/data/mods/Magiclysm/monstergroups.json b/data/mods/Magiclysm/monstergroups.json index 28f5d2b3cbbc5..e897a2dded748 100644 --- a/data/mods/Magiclysm/monstergroups.json +++ b/data/mods/Magiclysm/monstergroups.json @@ -25,10 +25,17 @@ "cost_multiplier": 5, "conditions": [ "NIGHT" ], "pack_size": [ 2, 4 ], - "starts": 1500 + "starts": 750 }, + { "monster": "mon_were_zolf", "freq": 4, "cost_multiplier": 5, "pack_size": [ 1, 2 ], "starts": 800 }, + { "monster": "mon_winter_wolf", "freq": 4, "cost_multiplier": 5, "pack_size": [ 1, 3 ], "starts": 750 }, { "monster": "mon_irongolem", "freq": 2, "cost_multiplier": 8 }, - { "monster": "mon_demon_spiderling", "freq": 15, "cost_multiplier": 5, "pack_size": [ 3, 7 ] } + { "monster": "mon_demon_spiderling", "freq": 15, "cost_multiplier": 5, "pack_size": [ 3, 7 ] }, + { "monster": "mon_owlbear_zombie", "freq": 7, "cost_multiplier": 10 }, + { "monster": "mon_owlbear_zombie_brute", "freq": 1, "cost_multiplier": 15 }, + { "monster": "mon_troll_zombie", "freq": 3, "cost_multiplier": 13 }, + { "monster": "mon_yulecat_zombie", "freq": 3, "cost_multiplier": 12 }, + { "monster": "mon_yulecat_zombie_brute", "freq": 1, "cost_multiplier": 25 } ] }, { @@ -54,7 +61,10 @@ "monsters": [ { "monster": "mon_owlbear", "freq": 100, "cost_multiplier": 10, "pack_size": [ 2, 4 ] }, { "monster": "mon_shrieker", "freq": 10, "cost_multiplier": 1 }, - { "monster": "mon_lemure", "freq": 5, "cost_multiplier": 2, "pack_size": [ 1, 4 ] } + { "monster": "mon_lemure", "freq": 5, "cost_multiplier": 2, "pack_size": [ 1, 4 ] }, + { "monster": "mon_owlbear_zombie", "freq": 40, "cost_multiplier": 10, "pack_size": [ 2, 4 ] }, + { "monster": "mon_owlbear_zombie_brute", "freq": 5, "cost_multiplier": 20, "pack_size": [ 1, 2 ] }, + { "monster": "mon_yulecat_zombie_brute", "freq": 5, "cost_multiplier": 30 } ] }, { diff --git a/data/mods/Magiclysm/monsters/holiday_magiclysm.json b/data/mods/Magiclysm/monsters/holiday_magiclysm.json index 45427ba3050e1..d7b97db8ee30c 100644 --- a/data/mods/Magiclysm/monsters/holiday_magiclysm.json +++ b/data/mods/Magiclysm/monsters/holiday_magiclysm.json @@ -31,7 +31,8 @@ "baby_flags": [ "WINTER" ], "special_attacks": [ { "type": "bite", "cooldown": 10 }, [ "GRAB", 8 ], [ "scratch", 6 ] ], "anger_triggers": [ "PLAYER_NEAR_BABY" ], - "flags": [ "SEES", "HEARS", "SMELLS", "KEENNOSE", "PATH_AVOID_DANGER_1", "WARM", "GRABS" ] + "flags": [ "SEES", "HEARS", "SMELLS", "KEENNOSE", "PATH_AVOID_DANGER_1", "WARM", "GRABS" ], + "zombify_into": "mon_yulecat_zombie" }, { "id": "mon_yulecat_cub", diff --git a/data/mods/Magiclysm/monsters/monsters.json b/data/mods/Magiclysm/monsters/monsters.json index 3342b6ab27a08..c9995ff249e81 100644 --- a/data/mods/Magiclysm/monsters/monsters.json +++ b/data/mods/Magiclysm/monsters/monsters.json @@ -30,7 +30,8 @@ "reproduction": { "baby_egg": "egg_owlbear_rock", "baby_count": 1, "baby_timer": 20 }, "baby_flags": [ "SPRING", "SUMMER", "AUTUMN", "WINTER" ], "special_attacks": [ { "type": "bite", "cooldown": 10 }, [ "GRAB", 7 ], [ "scratch", 7 ] ], - "flags": [ "SEES", "HEARS", "SMELLS", "KEENNOSE", "PATH_AVOID_DANGER_1", "WARM", "GRABS", "SWARMS" ] + "flags": [ "SEES", "HEARS", "SMELLS", "KEENNOSE", "PATH_AVOID_DANGER_1", "WARM", "GRABS", "SWARMS" ], + "zombify_into": "mon_owlbear_zombie" }, { "id": "mon_black_pudding", @@ -311,7 +312,8 @@ "harvest": "human_large_leather", "special_attacks": [ { "type": "bite", "cooldown": 30 }, [ "GRAB", 15 ], [ "scratch", 15 ], [ "slam", 10 ], [ "SMASH", 30 ] ], "regenerates": 1, - "flags": [ "SEES", "SMELLS", "KEENNOSE", "PATH_AVOID_DANGER_1", "WARM", "GRABS", "FLAMMABLE" ] + "flags": [ "SEES", "SMELLS", "KEENNOSE", "PATH_AVOID_DANGER_1", "WARM", "GRABS", "FLAMMABLE" ], + "zombify_into": "mon_troll_zombie" }, { "id": "mon_stirge", diff --git a/data/mods/Magiclysm/monsters/zombified_monsters.json b/data/mods/Magiclysm/monsters/zombified_monsters.json index c3b1583b25673..055dfff189b57 100644 --- a/data/mods/Magiclysm/monsters/zombified_monsters.json +++ b/data/mods/Magiclysm/monsters/zombified_monsters.json @@ -61,5 +61,161 @@ "vision_night": 12, "harvest": "orc", "flags": [ "SEES", "HEARS", "SMELLS", "STUMBLES", "WARM", "BASHES", "GROUP_BASH", "POISON", "NO_BREATHE", "REVIVES", "FILTHY" ] + }, + { + "type": "MONSTER", + "id": "mon_owlbear_zombie", + "name": "Zowlbear", + "description": "This horrible mutant monster has been zombified. Though it looks weaker than its living counterpart, you feel much more hostility from its black oily eyes.", + "default_faction": "zombie", + "bodytype": "bear", + "species": [ "MAGICAL_BEAST", "ZOMBIE" ], + "volume": "435000 ml", + "weight": "420 kg", + "looks_like": "mon_owlbear", + "hp": 220, + "speed": 105, + "material": [ "flesh" ], + "symbol": "W", + "color": "green", + "aggression": 100, + "morale": 100, + "melee_skill": 4, + "melee_dice": 4, + "melee_dice_sides": 6, + "melee_cut": 6, + "dodge": 1, + "armor_bash": 5, + "armor_cut": 2, + "armor_bullet": 2, + "vision_night": 13, + "path_settings": { "max_dist": 12 }, + "harvest": "zombie_owlbear", + "special_attacks": [ { "type": "bite", "cooldown": 10 }, [ "GRAB", 7 ], [ "scratch", 7 ] ], + "flags": [ + "SEES", + "HEARS", + "SMELLS", + "KEENNOSE", + "PATH_AVOID_DANGER_1", + "WARM", + "GRABS", + "SWARMS", + "STUMBLES", + "BASHES", + "POISON", + "NO_BREATHE", + "REVIVES" + ], + "upgrades": { "half_life": 60, "into": "mon_owlbear_zombie_brute" } + }, + { + "type": "MONSTER", + "id": "mon_owlbear_zombie_brute", + "copy-from": "mon_owlbear_zombie", + "name": "Zowlbear Predator", + "description": "An once zombified owlbear, now faster and much bigger in size. Its thick skin protects the monster from harm, a sharp beak capable of rending through metal and a fury in its eyes warns you to stay away.", + "upgrades": false, + "path_settings": { "max_dist": 0 }, + "proportional": { "volume": 1.15, "weight": 1.2 }, + "relative": { + "hp": 80, + "speed": 35, + "melee_skill": 2, + "melee_dice": 1, + "melee_dice_sides": 2, + "melee_cut": 4, + "dodge": 3, + "armor_bash": 3, + "armor_cut": 3, + "armor_bullet": 2, + "vision_night": 19 + }, + "delete": { "flags": [ "PATH_AVOID_DANGER_1" ] }, + "extend": { "special_attacks": [ [ "SMASH", 20 ] ] } + }, + { + "type": "MONSTER", + "id": "mon_troll_zombie", + "copy-from": "mon_troll", + "name": "Undying", + "description": "An enourmous humanoid monster with a yellowish-green skin. Trolls are renowned for their thick hides and natural regenerative ability. After death, its pus filled body seems to have much grown stronger, it looks at you ferociously with hunger in its eyes.", + "default_faction": "zombie", + "harvest": "zombie", + "relative": { + "hp": 40, + "speed": -25, + "melee_skill": -2, + "melee_dice": 2, + "melee_dice_sides": -1, + "melee_cut": -2, + "armor_bash": 2, + "armor_cut": 2, + "armor_bullet": 1, + "vision_day": -13, + "vision_night": 3, + "regenerates": 3 + }, + "proportional": { "volume": 1.05, "weight": 1.07 }, + "extend": { "species": [ "ZOMBIE" ], "flags": [ "BASHES", "POISON", "NO_BREATHE", "REVIVES" ] }, + "delete": { "flags": [ "PATH_AVOID_DANGER_1" ] } + }, + { + "type": "MONSTER", + "id": "mon_yulecat_zombie", + "name": "Zombified Yule Cat", + "description": "A magical beast from Icelandic folklore, known for their catlike appearance and their hobby of eating Workshop Elves. It creeply stumbles on its 4 legs with its squirming uneven body after meeting demise and being reborn just to eat you.", + "looks_like": "mon_yulecat", + "default_faction": "zombie", + "species": [ "MAGICAL_BEAST", "ZOMBIE" ], + "symbol": "Y", + "color": "white", + "material": [ "flesh" ], + "bodytype": "lion", + "weight": "763 kg", + "volume": "195 L", + "aggression": 100, + "morale": 100, + "hp": 215, + "speed": 124, + "melee_skill": 3, + "melee_dice": 5, + "melee_dice_sides": 7, + "melee_cut": 2, + "dodge": 3, + "armor_bash": 4, + "armor_cut": 1, + "armor_bullet": 4, + "vision_day": 30, + "vision_night": 10, + "path_settings": { "max_dist": 3, "avoid_traps": false, "avoid_sharp": false }, + "harvest": "zombie_fur", + "special_attacks": [ { "type": "bite", "cooldown": 10 }, [ "GRAB", 8 ], [ "scratch", 6 ] ], + "flags": [ "SEES", "HEARS", "SMELLS", "KEENNOSE", "WARM", "GRABS", "STUMBLES", "BASHES", "POISON", "NO_BREATHE", "REVIVES" ], + "upgrades": { "half_life": 5, "into": "mon_yulecat_zombie_brute" } + }, + { + "type": "MONSTER", + "id": "mon_yulecat_zombie_brute", + "copy-from": "mon_yulecat_zombie", + "name": "Tod Cat", + "description": "Once used to its decomposed body, this nightmarish cat with thick teeth and razorshap claws seems to be looking around for things to \"play\" with. Though its head is of a feline, it grins at you sadisticly with a glint in its cold demonic eyes.", + "path_settings": { "max_dist": 17 }, + "relative": { + "hp": 65, + "speed": 49, + "melee_skill": 5, + "melee_dice": 1, + "melee_dice_sides": 1, + "melee_cut": -2, + "armor_bash": 2, + "armor_cut": 1, + "armor_bullet": -2, + "vision_day": -22, + "vision_night": 20, + "regenerates": 3 + }, + "proportional": { "volume": 1.01, "weight": 0.95 }, + "extend": { "flags": [ "PATH_AVOID_DANGER_1" ], "special_attacks": [ { "type": "leap", "cooldown": 7, "max_range": 2 } ] } } ] diff --git a/data/mods/No_Fungi/modinfo.json b/data/mods/No_Fungi/modinfo.json index 3110518edd062..27278fadfc272 100644 --- a/data/mods/No_Fungi/modinfo.json +++ b/data/mods/No_Fungi/modinfo.json @@ -6,7 +6,8 @@ "authors": [ "Chaosvolt" ], "description": "Removes fungal monsters and regions from the game.", "category": "monster_exclude", - "dependencies": [ "dda" ] + "dependencies": [ "dda" ], + "obsolete": true }, { "type": "MONSTER_BLACKLIST", diff --git a/data/mods/No_Hope/Mapgen/house21.json b/data/mods/No_Hope/Mapgen/house21.json index f8ff714d173ad..279b631f586f2 100644 --- a/data/mods/No_Hope/Mapgen/house21.json +++ b/data/mods/No_Hope/Mapgen/house21.json @@ -112,7 +112,6 @@ }, "furniture": { "D": "f_dumpster", "P": "f_mailbox", "{": "f_dumpster" }, "place_item": [ - { "chance": 20, "item": "toolbox", "x": 14, "y": 10 }, { "chance": 30, "item": "glass_sheet", "x": 5, "y": 18 }, { "chance": 30, "item": "glass_sheet", "x": 6, "y": 18 }, { "chance": 30, "item": "101_carpentry", "x": 8, "y": 7 }, @@ -122,6 +121,7 @@ { "chance": 30, "item": "glass_sheet", "x": 7, "y": 19 } ], "place_items": [ + { "chance": 20, "item": "tools_toolbox", "x": 14, "y": 10 }, { "chance": 30, "item": "building_rubble", "x": 4, "y": 10 }, { "chance": 30, "item": "building_rubble", "x": [ 13, 14 ], "y": 4 }, { "chance": 30, "item": "building_rubble", "x": [ 12, 13 ], "y": 3 }, diff --git a/data/mods/No_Hope/Mapgen/private_resort.json b/data/mods/No_Hope/Mapgen/private_resort.json index 0cc1a9e9465b0..a7396ac56a7c1 100644 --- a/data/mods/No_Hope/Mapgen/private_resort.json +++ b/data/mods/No_Hope/Mapgen/private_resort.json @@ -1169,7 +1169,7 @@ "***WWWWWWWWWWWWWWWWWW***" ], "palettes": [ "p_resort_palette_basement" ], - "place_item": [ { "item": "toolbox", "repeat": 1, "x": 8, "y": 11 } ], + "place_loot": [ { "group": "tools_toolbox", "repeat": 1, "x": 8, "y": 11 } ], "items": { "S": { "item": "preserved_food", "chance": 50, "repeat": [ 0, 3 ] }, "f": { "item": "butcher_raw_meat", "chance": 50, "repeat": [ 0, 6 ] } diff --git a/data/mods/No_Hope/item_groups.json b/data/mods/No_Hope/item_groups.json index dea6a160cc552..9b7f6705a4922 100644 --- a/data/mods/No_Hope/item_groups.json +++ b/data/mods/No_Hope/item_groups.json @@ -133,5 +133,52 @@ { "group": "newspaper", "prob": 10 }, [ "handflare_dead", 3 ] ] + }, + { + "type": "item_group", + "id": "chickenbot", + "items": [ + [ "robot_controls", 5 ], + [ "ai_module", 5 ], + [ "sensor_module", 5 ], + [ "memory_module", 5 ], + [ "pathfinding_module", 5 ], + [ "identification_module", 5 ], + [ "reverse_jointed_legs", 40 ], + [ "chickenbot_chassis", 40 ], + [ "targeting_module", 5 ], + [ "gun_module", 30 ], + [ "mark19", 5 ], + [ "tazer", 5 ], + [ "m249", 5 ], + [ "storage_battery", 5 ], + [ "plut_cell", 5 ], + [ "mil_plate", 2 ] + ] + }, + { + "type": "item_group", + "id": "tankbot", + "items": [ + [ "tazer", 3 ], + { "item": "flamethrower", "prob": 1, "charges-min": 0, "charges-max": 3000 }, + [ "556", 8 ], + [ "alloy_plate", 10 ], + [ "kevlar_plate", 10 ], + [ "ceramic_armor", 10 ], + [ "hard_plate", 30 ], + [ "robot_controls", 5 ] + ] + }, + { + "type": "item_group", + "id": "tripod", + "items": [ + { "item": "flamethrower", "prob": 1, "charges-min": 0, "charges-max": 3000 }, + [ "kevlar_plate", 10 ], + [ "ceramic_armor", 15 ], + [ "alloy_plate", 10 ], + [ "robot_controls", 3 ] + ] } ] diff --git a/data/mods/No_Hope/items.json b/data/mods/No_Hope/items.json new file mode 100644 index 0000000000000..505e5a009a7fa --- /dev/null +++ b/data/mods/No_Hope/items.json @@ -0,0 +1,264 @@ +[ + { + "id": "schematics_chickenbot", + "type": "BOOK", + "name": { "str_sp": "chicken walker schematics" }, + "description": "Bearing the logo of Northrop, those are assembly plans, design specs, and technical drawings for the chicken walker. Most of this is useless to you, but you could use the assembly plans to re-assemble the robot from salvaged parts.", + "copy-from": "schematics_generic" + }, + { + "id": "schematics_tankbot", + "type": "BOOK", + "name": { "str_sp": "tank drone schematics" }, + "description": "Bearing the logo of Northrop, those are assembly plans, design specs, and technical drawings for the tank drone. Most of this is useless to you, but you could use the assembly plans to re-assemble the robot from salvaged parts.", + "copy-from": "schematics_generic" + }, + { + "id": "schematics_tripod", + "type": "BOOK", + "name": { "str_sp": "tripod schematics" }, + "description": "Bearing the logo of Honda, those are assembly plans, design specs, and technical drawings for the tripod. Most of this is useless to you, but you could use the assembly plans to re-assemble the robot from salvaged parts.", + "copy-from": "schematics_generic" + }, + { + "id": "bot_chickenbot", + "type": "TOOL", + "name": { "str": "inactive chicken walker" }, + "description": "This is an inactive chicken walker. Using this item involves placing it on the ground, loading the unit with the factory-loaded 5.56 rounds and 40mm cartridge grenades in your inventory (if you wish to divide your ammunition, set aside whatever ammunition you do NOT want to give the robot) and turning it on. If reprogrammed and rewired successfully the chicken walker will then identify you as a friendly, roam around or follow you, and attack all enemies with a built-in firearm and grenade launcher.", + "weight": "120000 g", + "volume": "92500 ml", + "price": 50000000, + "to_hit": -3, + "bashing": 8, + "material": [ "steel" ], + "symbol": ";", + "color": "light_green", + "use_action": { + "type": "place_monster", + "monster_id": "mon_chickenbot", + "friendly_msg": "The chicken walker rises to its feet, sways away from you and begins surveying the area.", + "hostile_msg": "The chicken walker whirrs and aims directly at you. Take cover!", + "//": "Milspec, but was deployed in active service implying a reliable IFF", + "difficulty": 9, + "moves": 250, + "skills": [ "electronics", "computer" ] + } + }, + { + "id": "bot_tankbot", + "looks_like": "broken_tankbot", + "type": "TOOL", + "name": { "str": "inactive tank drone" }, + "description": "This is an inactive Beagle Mini-Tank UGV. Using this item involves placing it on the ground, loading the unit with the factory-loaded 5.56 rounds and 40mm cartridge grenades in your inventory (if you wish to divide your ammunition, set aside whatever ammunition you do NOT want to give the robot) and turning it on. If reprogrammed and rewired successfully the tank drone will then identify you as a friendly, roam around or follow you, and attack all enemies with a built-in firearm and grenade launcher.", + "weight": "200000 g", + "//": "cheating a bit with the volume due to lack of proper vehicle storage options", + "volume": "250 L", + "price": 100000000, + "to_hit": -3, + "bashing": 8, + "material": [ "steel" ], + "symbol": ";", + "color": "light_green", + "use_action": { + "type": "place_monster", + "monster_id": "mon_tankbot", + "friendly_msg": "The tank drone rolls out and begins acquiring targets.", + "hostile_msg": "The tank drone swivels its turret and aims directly at you. Don your brown pants!", + "//": "Milspec, clearly designed with little concern for collateral damage. What did you expect of a robo-tank?", + "difficulty": 10, + "moves": 500, + "skills": [ "electronics", "computer" ] + } + }, + { + "type": "GENERIC", + "id": "broken_chickenbot", + "looks_like": "broken_tripod", + "symbol": ",", + "color": "green", + "name": { "str": "broken chickenbot" }, + "category": "other", + "description": "A broken chicken walker. Still looks intimidating despite being permanently inoperative, possibly due to the sheer size and mass. Could be gutted for parts.", + "price": 1000, + "material": [ "steel", "plastic" ], + "weight": "1023850 g", + "volume": "1100 L", + "bashing": 20, + "cutting": 15, + "to_hit": -3, + "use_action": { + "type": "place_monster", + "monster_id": "mon_chickenbot", + "friendly_msg": "The chicken bot rolls out and begins acquiring targets.", + "hostile_msg": "The chicken bot swivels its turret and aims directly at you. Don your brown pants!", + "//": "Milspec, clearly designed with little concern for collateral damage. What did you expect of a chicken walker?", + "difficulty": 10, + "moves": 500, + "skills": [ "electronics", "computer" ] + } + }, + { + "id": "bot_tripod", + "looks_like": "broken_tripod", + "type": "TOOL", + "name": { "str": "inactive tripod" }, + "description": "This is an inactive Honda Regnal. Using this item involves placing it on the ground, wondering how it fuels its flamethrower and turning it on. If reprogrammed and rewired successfully the tribot will then identify you as an ally, roam around or follow you, and impale hostiles with its spiked cable weapons.", + "weight": "120000 g", + "volume": "92500 ml", + "price": 100000000, + "to_hit": -3, + "bashing": 8, + "material": [ "steel" ], + "symbol": ";", + "color": "light_green", + "use_action": { + "type": "place_monster", + "monster_id": "mon_tripod", + "friendly_msg": "The tribot rises to its feet and scans the area for contaminants.", + "hostile_msg": "The tribot glowers down at you and ignites its flamethrower. Turns out you hate the smell of napalm.", + "//": "No observed open deployment, likely a prototype or secret project", + "difficulty": 15, + "moves": 500, + "skills": [ "electronics", "computer" ] + } + }, + { + "type": "GENERIC", + "id": "broken_tripod", + "symbol": ",", + "color": "green", + "name": { "str": "broken tribot" }, + "category": "other", + "description": "A broken tribot. Now that its legs lie broken and immobile, the world seems a little less threatening. Could be gutted for parts.", + "price": 1000, + "material": [ "steel", "plastic" ], + "weight": "430000 g", + "volume": "187500 ml", + "bashing": 10, + "cutting": 6, + "to_hit": -2, + "flags": [ "TRADER_AVOID", "NO_REPAIR" ] + }, + { + "type": "GENERIC", + "id": "broken_tankbot", + "symbol": ",", + "color": "green", + "name": { "str": "broken tank drone" }, + "category": "other", + "description": "A broken tank drone. Still looks intimidating despite being permanently inoperative, possibly due to the sheer size and mass. Could be gutted for parts.", + "price": 1000, + "material": [ "steel", "plastic" ], + "weight": "1223850 g", + "volume": "875 L", + "bashing": 20, + "cutting": 15, + "to_hit": -3, + "flags": [ "TRADER_AVOID", "NO_REPAIR" ] + }, + { + "type": "GENERIC", + "id": "tripod_chassis", + "name": { "str_sp": "tripod chassis" }, + "description": "What's left when you remove all moving parts and electronics. It's the skeleton and armor of the tripod.", + "symbol": "c", + "color": "light_gray", + "weight": "40000 g", + "volume": "70000 ml", + "price": 200000, + "material": [ "steel" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "chickenbot_chassis", + "name": { "str_sp": "chicken walker chassis" }, + "description": "What's left when you remove all moving parts and electronics. It's the skeleton and armor of the chicken walker.", + "symbol": "c", + "color": "light_gray", + "weight": "60000 g", + "volume": "80000 ml", + "price": 300000, + "material": [ "steel" ], + "category": "spare_parts" + }, + { + "type": "GENERIC", + "id": "tankbot_chassis", + "name": { "str_sp": "Beagle chassis" }, + "description": "What's left when you remove all moving parts and electronics. It's the skeleton and armor of the Beagle tank.", + "symbol": "c", + "color": "light_gray", + "weight": "150000 g", + "volume": "575000 ml", + "price": 1000000, + "material": [ "steel" ], + "category": "spare_parts" + }, + { + "id": "TANK", + "looks_like": "m79", + "type": "GUN", + "symbol": "(", + "color": "green", + "name": { "str_sp": "Tankbot Main Gun" }, + "description": "The 120mm cannon from a tankbot. If you have this, you'd best be debugging!", + "price": 99999999, + "material": [ "steel" ], + "skill": "launcher", + "ammo": [ "120mm" ], + "weight": "2500 g", + "volume": "2500 ml", + "bashing": 6, + "to_hit": -3, + "dispersion": 60, + "durability": 9, + "clip_size": 1, + "loudness": 300, + "pocket_data": [ { "pocket_type": "MAGAZINE", "ammo_restriction": { "120mm": 1 } } ] + }, + { + "type": "GENERIC", + "id": "spidery_legs_big", + "name": { "str": "set of spidery legs", "str_pl": "sets of spidery legs" }, + "description": "A set of big pointy legs, like the ones found under a tripod.", + "symbol": "W", + "color": "light_gray", + "weight": "40000 g", + "volume": "20 L", + "price": 200000, + "material": [ "steel" ], + "category": "spare_parts" + }, + { + "id": "bot_laserturret", + "type": "TOOL", + "name": { "str": "inactive laser turret" }, + "description": "This is an inactive laser turret. Using this item involves turning it on and placing it on the ground, where it will attach itself. If reprogrammed and rewired successfully the turret will identify you as a friendly, and attack all enemies with its revolving laser cannons. It requires sunlight in order to fire.", + "weight": "40750 g", + "volume": "30 L", + "price": 600000, + "price_postapoc": 12000, + "to_hit": -3, + "bashing": 8, + "material": [ "steel", "plastic" ], + "symbol": ";", + "color": "white", + "use_action": { + "type": "place_monster", + "monster_id": "mon_laserturret", + "difficulty": 6, + "moves": 100, + "skills": [ "electronics", "computer" ] + } + }, + { + "type": "GENERIC", + "id": "broken_laserturret", + "symbol": ",", + "color": "green", + "name": { "str": "broken laser turret" }, + "weight": "110 kg", + "copy-from": "broken_turret" + } +] diff --git a/data/mods/TEST_DATA/effects.json b/data/mods/TEST_DATA/effects.json index 0069a87d459bf..d60393de8507c 100644 --- a/data/mods/TEST_DATA/effects.json +++ b/data/mods/TEST_DATA/effects.json @@ -11,6 +11,7 @@ "max_duration": "1 h", "max_intensity": 10, "int_decay_tick": 2, + "int_decay_remove": true, "base_mods": { "str_mod": [ 1 ], "dex_mod": [ 2 ], diff --git a/data/mods/TEST_DATA/overmap_specials.json b/data/mods/TEST_DATA/overmap_specials.json new file mode 100644 index 0000000000000..f0bfa1d52c54c --- /dev/null +++ b/data/mods/TEST_DATA/overmap_specials.json @@ -0,0 +1,58 @@ +[ + { + "type": "overmap_special", + "id": "test_anthill", + "subtype": "mutable", + "locations": [ "subterranean_empty" ], + "city_distance": [ 10, -1 ], + "occurrences": [ 80, 100 ], + "flags": [ "ANT", "UNIQUE", "CLASSIC", "WILDERNESS" ], + "check_for_locations": [ + [ [ 0, 0, 0 ], [ "land" ] ], + [ [ 0, 0, -1 ], [ "subterranean_empty" ] ], + [ [ 1, 0, -1 ], [ "subterranean_empty" ] ], + [ [ 0, 1, -1 ], [ "subterranean_empty" ] ], + [ [ -1, 0, -1 ], [ "subterranean_empty" ] ], + [ [ 0, -1, -1 ], [ "subterranean_empty" ] ] + ], + "joins": [ "surface_to_tunnel", "tunnel_to_tunnel" ], + "overmaps": { + "surface": { "overmap": "anthill_north", "below": "surface_to_tunnel", "locations": [ "land" ] }, + "below_entrance": { + "overmap": "ants_nesw", + "above": "surface_to_tunnel", + "north": "tunnel_to_tunnel", + "east": "tunnel_to_tunnel", + "south": "tunnel_to_tunnel", + "west": "tunnel_to_tunnel" + }, + "crossroads": { + "overmap": "ants_nesw", + "north": "tunnel_to_tunnel", + "east": "tunnel_to_tunnel", + "south": "tunnel_to_tunnel", + "west": "tunnel_to_tunnel" + }, + "tee": { "overmap": "ants_nes", "north": "tunnel_to_tunnel", "east": "tunnel_to_tunnel", "south": "tunnel_to_tunnel" }, + "straight_tunnel": { "overmap": "ants_ns", "north": "tunnel_to_tunnel", "south": "tunnel_to_tunnel" }, + "corner": { "overmap": "ants_ne", "north": "tunnel_to_tunnel", "east": "tunnel_to_tunnel" }, + "dead_end": { "overmap": "ants_end_south", "north": "tunnel_to_tunnel" } + }, + "root": "surface", + "phases": [ + [ { "overmap": "below_entrance", "max": 1 } ], + [ + { "overmap": "straight_tunnel", "max": 20 }, + { "overmap": "corner", "max": 5 }, + { "overmap": "tee", "max": 10 } + ], + [ + { "overmap": "dead_end", "weight": 2000 }, + { "overmap": "straight_tunnel", "weight": 100 }, + { "overmap": "corner", "weight": 100 }, + { "overmap": "tee", "weight": 10 }, + { "overmap": "crossroads", "weight": 1 } + ] + ] + } +] diff --git a/data/mods/default.json b/data/mods/default.json index 6271c6c613b36..e98c8dc9d745a 100644 --- a/data/mods/default.json +++ b/data/mods/default.json @@ -4,6 +4,6 @@ "id": "dev:default", "name": "default", "description": "contains all the mods recommended by the developers", - "dependencies": [ "dda", "no_npc_food", "package_bionic_professions" ] + "dependencies": [ "dda", "no_npc_food", "no_fungal_growth", "package_bionic_professions" ] } ] diff --git a/doc/COMPILING/COMPILING-VS-VCPKG.md b/doc/COMPILING/COMPILING-VS-VCPKG.md index 730a40de6c81b..54b1fc934e8f3 100644 --- a/doc/COMPILING/COMPILING-VS-VCPKG.md +++ b/doc/COMPILING/COMPILING-VS-VCPKG.md @@ -33,35 +33,6 @@ cd vcpkg .\vcpkg integrate install ``` -4. Install a necessary pre-requisite package: - -#### Install YASM-tool: - -```cmd -.\vcpkg --triplet x86-windows install yasm-tool yasm-tool-helper -``` - -5. Install the dependencies for your desired architecture. - - -#### 64-bit dependencies: - -```cmd -.\vcpkg --triplet x64-windows-static install sdl2 sdl2-image sdl2-mixer[libflac,mpg123,libmodplug,libvorbis] sdl2-ttf gettext -``` - -#### 32-bit dependencies: - -```cmd -.\vcpkg --triplet x86-windows-static install sdl2 sdl2-image sdl2-mixer[libflac,mpg123,libmodplug,libvorbis] sdl2-ttf gettext -``` - -#### upgrade all dependencies: - -```cmd -.\vcpkg upgrade -``` - ## Cloning and compilation: 1. Clone Cataclysm-DDA repository with following command line: @@ -79,7 +50,7 @@ cd Cataclysm-DDA This will configure Visual Studio to compile the release version, with support for Sound, Tiles, and Localization (note, however, that language files themselves are not automatically compiled; this will be done later). -4. Start the build process by selecting either `Build > Build Solution` or `Build > Build > 1 Cataclysm-vcpkg-static`. The process may take a long period of time, so you'd better prepare a cup of coffee and some books in front of your computer :) +4. Start the build process by selecting either `Build > Build Solution` or `Build > Build > 1 Cataclysm-vcpkg-static`. The process may take a long period of time, so you'd better prepare a cup of coffee and some books in front of your computer :) The first build of each architecture will also download and install dependencies through vcpkg, which can take an especially long time. 5. If you need localization support, execute the bash script `lang/compile_mo.sh` inside Git Bash GUI just like on a UNIX-like system. This will compile the language files that were not automatically compiled in step 2 above. diff --git a/doc/EFFECTS_JSON.md b/doc/EFFECTS_JSON.md index 0860f8e847f29..09ecc69044cf2 100644 --- a/doc/EFFECTS_JSON.md +++ b/doc/EFFECTS_JSON.md @@ -235,7 +235,7 @@ Intensities are used to control effect effects, names, and descriptions. They ar "int_decay_step": -2, - Int, default -1, intensity levels removed every decay tick "int_decay_tick": 10 - Int, seconds between intensity decay (no decay at the default of 0) - "int_decay_remove": true - Bool, default true, removes the intensity if decay would decrease it to zero + "int_decay_remove": true - Bool, default false, removes the intensity if decay would decrease it to zero or "int_dur_factor": 700 ``` diff --git a/msvc-full-features/Cataclysm-common.props b/msvc-full-features/Cataclysm-common.props index 0bbd1df8e3ad3..a9a279ee284fe 100644 --- a/msvc-full-features/Cataclysm-common.props +++ b/msvc-full-features/Cataclysm-common.props @@ -7,6 +7,9 @@ $(MSBuildThisFileDirectory)..\ $(SolutionDir)$(ProjectName)\$(Configuration)\$(Platform)\ + + --clean-after-build + Level1 diff --git a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj index e37e834a2f336..36ba9f2fd8884 100644 --- a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj @@ -33,8 +33,8 @@ true true true - x86-windows - x64-windows + x86-windows-static + x64-windows-static $(Configuration) diff --git a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj index a4f9feef51f62..59c79d81a2841 100644 --- a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj @@ -33,8 +33,8 @@ false true true - x86-windows - x64-windows + x86-windows-static + x64-windows-static $(Configuration) diff --git a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj index bd0dd4a506962..f98e74873964e 100644 --- a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj @@ -33,8 +33,8 @@ false true true - x86-windows - x64-windows + x86-windows-static + x64-windows-static $(Configuration) diff --git a/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj b/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj index 5201f5fee95d3..be41ffcb476a1 100644 --- a/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj +++ b/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj @@ -33,8 +33,8 @@ false true true - x86-windows - x64-windows + x86-windows-static + x64-windows-static $(Configuration) diff --git a/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj b/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj index 284def1dbe416..701cb1c8650c1 100644 --- a/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj +++ b/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj @@ -33,8 +33,8 @@ false true true - x86-windows - x64-windows + x86-windows-static + x64-windows-static $(Configuration) diff --git a/msvc-full-features/vcpkg.json b/msvc-full-features/vcpkg.json index 7f3b25de574bc..5f77f8a645bc5 100644 --- a/msvc-full-features/vcpkg.json +++ b/msvc-full-features/vcpkg.json @@ -10,5 +10,6 @@ }, "sdl2-ttf", "gettext" - ] + ], + "builtin-baseline": "49b67d9cb856424ff69f10e7721aec5299624268" } diff --git a/msvc-object_creator/ObjectCreator-vcpkg-static.vcxproj b/msvc-object_creator/ObjectCreator-vcpkg-static.vcxproj index 12fcb1637ecdf..91103c8eff31b 100644 --- a/msvc-object_creator/ObjectCreator-vcpkg-static.vcxproj +++ b/msvc-object_creator/ObjectCreator-vcpkg-static.vcxproj @@ -33,8 +33,8 @@ true true true - x86-windows - x64-windows + x86-windows-static + x64-windows-static $(Configuration) @@ -74,7 +74,6 @@ Console - Netapi32.lib;userenv.lib;Ws2_32.lib;Wtsapi32.lib;Dwmapi.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;qwindows.lib;%(AdditionalDependencies) @@ -84,6 +83,9 @@ _DEBUG;%(PreprocessorDefinitions) MultiThreadedDebug + + Netapi32.lib;userenv.lib;Ws2_32.lib;Wtsapi32.lib;Dwmapi.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies) + @@ -97,9 +99,23 @@ true true + Netapi32.lib;userenv.lib;Ws2_32.lib;Wtsapi32.lib;Dwmapi.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;qwindows.lib;%(AdditionalDependencies) + + + + + WIN32;%(PreprocessorDefinitions) + + + .\vcpkg_installed\x86-windows-static\debug\plugins\platforms;%(AdditionalLibraryDirectories) + + + + + .\vcpkg_installed\x64-windows-static\debug\plugins\platforms;%(AdditionalLibraryDirectories) - + WIN32;%(PreprocessorDefinitions) @@ -107,7 +123,7 @@ .\vcpkg_installed\x86-windows-static\plugins\platforms;%(AdditionalLibraryDirectories) - + .\vcpkg_installed\x64-windows-static\plugins\platforms;%(AdditionalLibraryDirectories) diff --git a/msvc-object_creator/vcpkg.json b/msvc-object_creator/vcpkg.json index 03a1e75919863..b467582a5d1b0 100644 --- a/msvc-object_creator/vcpkg.json +++ b/msvc-object_creator/vcpkg.json @@ -11,5 +11,6 @@ "sdl2-ttf", "gettext", "qt5-base" - ] + ], + "builtin-baseline": "49b67d9cb856424ff69f10e7721aec5299624268" } diff --git a/src/action.cpp b/src/action.cpp index 6fd3421c0165a..4e4c622ec1712 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -732,9 +732,9 @@ action_id handle_action_menu() if( !player_character.controlling_vehicle ) { action_weightings[ACTION_CYCLE_MOVE] = 400; } - const item *weapon = player_character.get_wielded_item(); + const item &weapon = player_character.get_wielded_item(); // Only prioritize fire weapon options if we're wielding a ranged weapon. - if( weapon->is_gun() || weapon->has_flag( flag_REACH_ATTACK ) ) { + if( weapon.is_gun() || weapon.has_flag( flag_REACH_ATTACK ) ) { action_weightings[ACTION_FIRE] = 350; } } diff --git a/src/activity_actor.cpp b/src/activity_actor.cpp index 7430c30826715..bc3a972fc2ed2 100644 --- a/src/activity_actor.cpp +++ b/src/activity_actor.cpp @@ -297,8 +297,8 @@ item *aim_activity_actor::get_weapon() } else { // Check for lost gun (e.g. yanked by zombie technician) // TODO: check that this is the same gun that was used to start aiming - item *weapon = get_player_character().get_wielded_item(); - return weapon->is_null() ? nullptr : weapon; + item &weapon = get_player_character().get_wielded_item(); + return weapon.is_null() ? nullptr : &weapon; } } @@ -3873,7 +3873,7 @@ void reload_activity_actor::finish( player_activity &act, Character &who ) reloadable_name ); if( who.has_wield_conflicts( reloadable ) ) { reload_query.addentry( 1, wield_check, 'w', - _( "Dispose of %s and wield %s" ), who.get_wielded_item()->display_name(), + _( "Dispose of %s and wield %s" ), who.get_wielded_item().display_name(), reloadable_name ); } else { reload_query.addentry( 1, wield_check, 'w', _( "Wield %s" ), reloadable_name ); diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index d87edb4cd2b5d..a48ba24322e37 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -1808,19 +1808,19 @@ void activity_handlers::pulp_do_turn( player_activity *act, Character *you ) map &here = get_map(); const tripoint &pos = here.getlocal( act->placement ); - const item *weapon = you->get_wielded_item(); + const item &weapon = you->get_wielded_item(); // Stabbing weapons are a lot less effective at pulping - const int cut_power = std::max( weapon->damage_melee( damage_type::CUT ), - weapon->damage_melee( damage_type::STAB ) / 2 ); + const int cut_power = std::max( weapon.damage_melee( damage_type::CUT ), + weapon.damage_melee( damage_type::STAB ) / 2 ); ///\EFFECT_STR increases pulping power, with diminishing returns - float pulp_power = std::sqrt( ( you->str_cur + weapon->damage_melee( damage_type::BASH ) ) * + float pulp_power = std::sqrt( ( you->str_cur + weapon.damage_melee( damage_type::BASH ) ) * ( cut_power + 1.0f ) ); - float pulp_effort = you->str_cur + weapon->damage_melee( damage_type::BASH ); + float pulp_effort = you->str_cur + weapon.damage_melee( damage_type::BASH ); // Multiplier to get the chance right + some bonus for survival skill pulp_power *= 40 + you->get_skill_level( skill_survival ) * 5; - const int mess_radius = weapon->has_flag( flag_MESSY ) ? 2 : 1; + const int mess_radius = weapon.has_flag( flag_MESSY ) ? 2 : 1; int moves = 0; // use this to collect how many corpse are pulped diff --git a/src/advanced_inv_pane.cpp b/src/advanced_inv_pane.cpp index ac2627bb098c8..fe5b399dcdbb4 100644 --- a/src/advanced_inv_pane.cpp +++ b/src/advanced_inv_pane.cpp @@ -146,11 +146,11 @@ std::vector avatar::get_AIM_inventory( const advanced_inv } } } - item *weapon = get_wielded_item(); - if( weapon->is_container() ) { + item &weapon = get_wielded_item(); + if( weapon.is_container() ) { for( const std::vector &it_stack : item_list_to_stack( - item_location( *this, weapon ), - weapon->all_items_top( item_pocket::pocket_type::CONTAINER ) ) ) { + item_location( *this, &weapon ), + weapon.all_items_top( item_pocket::pocket_type::CONTAINER ) ) ) { advanced_inv_listitem adv_it( it_stack, item_index++, square.id, false ); if( !pane.is_filtered( *adv_it.items.front() ) ) { square.volume += adv_it.volume; @@ -181,9 +181,9 @@ void advanced_inventory_pane::add_items_from_area( advanced_inv_area &square, square.volume = 0_ml; square.weight = 0_gram; - item *weapon = u.get_wielded_item(); - if( !weapon->is_null() ) { - advanced_inv_listitem it( item_location( u, weapon ), 0, 1, square.id, false ); + item &weapon = u.get_wielded_item(); + if( !weapon.is_null() ) { + advanced_inv_listitem it( item_location( u, &weapon ), 0, 1, square.id, false ); if( !is_filtered( *it.items.front() ) ) { square.volume += it.volume; square.weight += it.weight; diff --git a/src/avatar.cpp b/src/avatar.cpp index 381ba081179b2..d29bf8ebd9a68 100644 --- a/src/avatar.cpp +++ b/src/avatar.cpp @@ -1329,8 +1329,8 @@ bool avatar::wield( item &target, const int obtain_cost ) return true; } - item *weapon = get_wielded_item(); - if( weapon->has_item( target ) ) { + item &weapon = get_wielded_item(); + if( weapon.has_item( target ) ) { add_msg( m_info, _( "You need to put the bag away before trying to wield something from it." ) ); return false; } @@ -1339,7 +1339,7 @@ bool avatar::wield( item &target, const int obtain_cost ) return false; } - bool combine_stacks = target.can_combine( *weapon ); + bool combine_stacks = target.can_combine( weapon ); if( !combine_stacks && !unwield() ) { return false; } @@ -1366,28 +1366,28 @@ bool avatar::wield( item &target, const int obtain_cost ) if( has_item( target ) ) { item removed = i_rem( &target ); if( combine_stacks ) { - weapon->combine( removed ); + weapon.combine( removed ); } else { set_wielded_item( removed ); } } else { if( combine_stacks ) { - weapon->combine( target ); + weapon.combine( target ); } else { set_wielded_item( target ); } } - last_item = weapon->typeId(); + last_item = weapon.typeId(); recoil = MAX_RECOIL; - weapon->on_wield( *this ); + weapon.on_wield( *this ); get_event_bus().send( getID(), last_item ); - inv->update_invlet( *weapon ); - inv->update_cache_with_item( *weapon ); + inv->update_invlet( weapon ); + inv->update_cache_with_item( weapon ); return true; } diff --git a/src/avatar_action.cpp b/src/avatar_action.cpp index ad124ae309f88..8cf26d28dba44 100644 --- a/src/avatar_action.cpp +++ b/src/avatar_action.cpp @@ -155,7 +155,7 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d ) } // If any leg broken without crutches and not already on the ground topple over - if( ( you.get_working_leg_count() < 2 && !you.get_wielded_item()->has_flag( flag_CRUTCHES ) ) && + if( ( you.get_working_leg_count() < 2 && !you.get_wielded_item().has_flag( flag_CRUTCHES ) ) && !you.is_prone() ) { you.set_movement_mode( move_mode_id( "prone" ) ); you.add_msg_if_player( m_bad, @@ -187,20 +187,20 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d ) via_ramp = true; } - item *weapon = you.get_wielded_item(); + item &weapon = you.get_wielded_item(); if( m.has_flag( ter_furn_flag::TFLAG_MINEABLE, dest_loc ) && g->mostseen == 0 && get_option( "AUTO_FEATURES" ) && get_option( "AUTO_MINING" ) && !m.veh_at( dest_loc ) && !you.is_underwater() && !you.has_effect( effect_stunned ) && !is_riding && !you.has_effect( effect_incorporeal ) ) { - if( weapon->has_flag( flag_DIG_TOOL ) ) { - if( weapon->type->can_use( "JACKHAMMER" ) && - weapon->ammo_sufficient( &you ) ) { - you.invoke_item( weapon, "JACKHAMMER", dest_loc ); + if( weapon.has_flag( flag_DIG_TOOL ) ) { + if( weapon.type->can_use( "JACKHAMMER" ) && + weapon.ammo_sufficient( &you ) ) { + you.invoke_item( &weapon, "JACKHAMMER", dest_loc ); // don't move into the tile until done mining you.defer_move( dest_loc ); return true; - } else if( weapon->type->can_use( "PICKAXE" ) ) { - you.invoke_item( weapon, "PICKAXE", dest_loc ); + } else if( weapon.type->can_use( "PICKAXE" ) ) { + you.invoke_item( &weapon, "PICKAXE", dest_loc ); // don't move into the tile until done mining you.defer_move( dest_loc ); return true; @@ -667,8 +667,8 @@ static float rate_critter( const Creature &c ) void avatar_action::autoattack( avatar &you, map &m ) { - const item *weapon = you.get_wielded_item(); - int reach = weapon->reach_range( you ); + const item &weapon = you.get_wielded_item(); + int reach = weapon.reach_range( you ); std::vector critters = you.get_targetable_creatures( reach, true ); critters.erase( std::remove_if( critters.begin(), critters.end(), [&you, reach]( const Creature * c ) { @@ -794,18 +794,18 @@ static bool can_fire_turret( avatar &you, const map &m, const turret_data &turre void avatar_action::fire_wielded_weapon( avatar &you ) { - const item *weapon = you.get_wielded_item(); - if( weapon->is_gunmod() ) { + const item &weapon = you.get_wielded_item(); + if( weapon.is_gunmod() ) { add_msg( m_info, _( "The %s must be attached to a gun, it can not be fired separately." ), - weapon->tname() ); + weapon.tname() ); return; - } else if( !weapon->is_gun() ) { + } else if( !weapon.is_gun() ) { return; - } else if( weapon->ammo_data() && - !weapon->ammo_types().count( weapon->loaded_ammo().ammo_type() ) ) { + } else if( weapon.ammo_data() && + !weapon.ammo_types().count( weapon.loaded_ammo().ammo_type() ) ) { add_msg( m_info, _( "The %s can't be fired while loaded with incompatible ammunition %s" ), - weapon->tname(), weapon->ammo_current()->nname( 1 ) ); + weapon.tname(), weapon.ammo_current()->nname( 1 ) ); return; } @@ -849,7 +849,7 @@ void avatar_action::mend( avatar &you, item_location loc ) if( !loc ) { if( you.is_armed() ) { - loc = item_location( you, you.get_wielded_item() ); + loc = item_location( you, &you.get_wielded_item() ); } else { add_msg( m_info, _( "You're not wielding anything." ) ); return; @@ -1027,8 +1027,8 @@ void avatar_action::plthrow( avatar &you, item_location loc, g->temp_exit_fullscreen(); - item *weapon = you.get_wielded_item(); - target_handler::trajectory trajectory = target_handler::mode_throw( you, *weapon, + item &weapon = you.get_wielded_item(); + target_handler::trajectory trajectory = target_handler::mode_throw( you, weapon, blind_throw_from_pos.has_value() ); // If we previously shifted our position, put ourselves back now that we've picked our target. @@ -1040,8 +1040,8 @@ void avatar_action::plthrow( avatar &you, item_location loc, return; } - if( weapon->count_by_charges() && weapon->charges > 1 ) { - weapon->mod_charges( -1 ); + if( weapon.count_by_charges() && weapon.charges > 1 ) { + weapon.mod_charges( -1 ); thrown.charges = 1; } else { you.remove_weapon(); diff --git a/src/bionics.cpp b/src/bionics.cpp index 97e7dd724bd24..b98a0a55708f4 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -583,7 +583,7 @@ void npc::check_or_use_weapon_cbm( const bionic_id &cbm_id ) } bionic &bio = ( *my_bionics )[index]; - item *weapon = get_wielded_item(); + item &weapon = get_wielded_item(); if( bio.info().has_flag( json_flag_BIONIC_GUN ) ) { if( !bio.has_weapon() ) { debugmsg( "NPC tried to activate gun bionic \"%s\" without fake_weapon", @@ -598,19 +598,19 @@ void npc::check_or_use_weapon_cbm( const bionic_id &cbm_id ) return; } - int ammo_count = weapon->ammo_remaining( this ); - const int ups_drain = weapon->get_gun_ups_drain(); + int ammo_count = weapon.ammo_remaining( this ); + const int ups_drain = weapon.get_gun_ups_drain(); if( ups_drain > 0 ) { ammo_count = ammo_count / ups_drain; } const int cbm_ammo = free_power / bio.info().power_activate; - if( weapon_value( *weapon, ammo_count ) < weapon_value( cbm_weapon, cbm_ammo ) ) { - real_weapon = *weapon; + if( weapon_value( weapon, ammo_count ) < weapon_value( cbm_weapon, cbm_ammo ) ) { + real_weapon = weapon; set_wielded_item( cbm_weapon ); cbm_weapon_index = index; } - } else if( bio.info().has_flag( json_flag_BIONIC_WEAPON ) && !weapon->has_flag( flag_NO_UNWIELD ) && + } else if( bio.info().has_flag( json_flag_BIONIC_WEAPON ) && !weapon.has_flag( flag_NO_UNWIELD ) && free_power > bio.info().power_activate ) { if( !bio.has_weapon() ) { @@ -620,7 +620,7 @@ void npc::check_or_use_weapon_cbm( const bionic_id &cbm_id ) } if( is_armed() ) { - stow_item( *weapon ); + stow_item( weapon ); } add_msg_if_player_sees( pos(), m_info, _( "%s activates their %s." ), disp_name(), bio.info().name ); @@ -640,7 +640,7 @@ void npc::check_or_use_weapon_cbm( const bionic_id &cbm_id ) bool Character::activate_bionic( int b, bool eff_only, bool *close_bionics_ui ) { - item *weapon = get_wielded_item(); + item &weapon = get_wielded_item(); bionic &bio = ( *my_bionics )[b]; const bool mounted = is_mounted(); if( bio.incapacitated_time > 0_turns ) { @@ -650,9 +650,9 @@ bool Character::activate_bionic( int b, bool eff_only, bool *close_bionics_ui ) } // Special compatibility code for people who updated saves with their claws out - if( ( weapon->typeId().str() == bio_claws_weapon.str() && + if( ( weapon.typeId().str() == bio_claws_weapon.str() && bio.id == bio_claws_weapon ) || - ( weapon->typeId().str() == bio_blade_weapon.str() && + ( weapon.typeId().str() == bio_blade_weapon.str() && bio.id == bio_blade_weapon ) ) { return deactivate_bionic( b ); } @@ -728,7 +728,7 @@ bool Character::activate_bionic( int b, bool eff_only, bool *close_bionics_ui ) return false; } - if( weapon->has_flag( flag_NO_UNWIELD ) ) { + if( weapon.has_flag( flag_NO_UNWIELD ) ) { cata::optional active_bio_weapon_index = active_bionic_weapon_index(); if( active_bio_weapon_index && deactivate_bionic( *active_bio_weapon_index, eff_only ) ) { // restore state and try again @@ -738,15 +738,15 @@ bool Character::activate_bionic( int b, bool eff_only, bool *close_bionics_ui ) return activate_bionic( b, eff_only, close_bionics_ui ); } - add_msg_if_player( m_info, _( "Deactivate your %s first!" ), weapon->tname() ); + add_msg_if_player( m_info, _( "Deactivate your %s first!" ), weapon.tname() ); refund_power(); bio.powered = false; return false; } - if( !weapon->is_null() ) { - const std::string query = string_format( _( "Stop wielding %s?" ), weapon->tname() ); - if( !dispose_item( item_location( *this, weapon ), query ) ) { + if( !weapon.is_null() ) { + const std::string query = string_format( _( "Stop wielding %s?" ), weapon.tname() ); + if( !dispose_item( item_location( *this, &weapon ), query ) ) { refund_power(); bio.powered = false; return false; @@ -756,7 +756,7 @@ bool Character::activate_bionic( int b, bool eff_only, bool *close_bionics_ui ) add_msg_activate(); set_wielded_item( bio.get_weapon() ); - get_wielded_item()->invlet = '#'; + get_wielded_item().invlet = '#'; //if( bio.ammo_count > 0 ) { // weapon.ammo_set( bio.ammo_loaded, bio.ammo_count ); // avatar_action::fire_wielded_weapon( player_character ); @@ -1215,7 +1215,7 @@ bool Character::deactivate_bionic( int b, bool eff_only ) bio.powered = false; add_msg_if_player( m_neutral, _( "You deactivate your %s." ), bio.info().name ); } - const item &w_weapon = *get_wielded_item(); + const item &w_weapon = get_wielded_item(); // Deactivation effects go here if( bio.info().has_flag( json_flag_BIONIC_WEAPON ) && !bio.info().fake_weapon.is_empty() ) { if( w_weapon.typeId() == bio.info().fake_weapon ) { @@ -1227,7 +1227,7 @@ bool Character::deactivate_bionic( int b, bool eff_only ) add_msg_if_npc( m_info, _( " withdraws her %s." ), w_weapon.tname() ); } } - bio.set_weapon( *get_wielded_item() ); + bio.set_weapon( get_wielded_item() ); set_wielded_item( item() ); } } else if( bio.id == bio_cqb ) { diff --git a/src/character.cpp b/src/character.cpp index c889c2295d653..582421c22aa4a 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -527,9 +527,9 @@ const item &Character::get_wielded_item() const return weapon; } -item *Character::get_wielded_item() +item &Character::get_wielded_item() { - return &weapon; + return weapon; } void Character::set_wielded_item( const item &to_wield ) @@ -1283,14 +1283,14 @@ bool Character::is_mounted() const void Character::forced_dismount() { - item *weapon = get_wielded_item(); + item &weapon = get_wielded_item(); remove_effect( effect_riding ); bool mech = false; if( mounted_creature ) { auto *mon = mounted_creature.get(); if( mon->has_flag( MF_RIDEABLE_MECH ) && !mon->type->mech_weapon.is_empty() ) { mech = true; - remove_item( *weapon ); + remove_item( weapon ); } mon->mounted_player_id = character_id(); mon->remove_effect( effect_ridden ); @@ -1395,13 +1395,13 @@ void Character::dismount() add_msg( m_warning, _( "You cannot dismount there!" ) ); return; } - item *weapon = get_wielded_item(); + item &weapon = get_wielded_item(); remove_effect( effect_riding ); monster *critter = mounted_creature.get(); critter->mounted_player_id = character_id(); if( critter->has_flag( MF_RIDEABLE_MECH ) && !critter->type->mech_weapon.is_empty() && - weapon->typeId() == critter->type->mech_weapon ) { - remove_item( *weapon ); + weapon.typeId() == critter->type->mech_weapon ) { + remove_item( weapon ); } avatar &player_character = get_avatar(); if( is_avatar() && player_character.get_grab_type() != object_type::NONE ) { @@ -1455,10 +1455,10 @@ void Character::on_dodge( Creature *source, float difficulty ) // Each avoided hit consumes an available dodge // When no more available we are likely to fail player::dodge_roll dodges_left--; - const item *weapon = get_wielded_item(); + const item &weapon = get_wielded_item(); // dodging throws of our aim unless we are either skilled at dodging or using a small weapon - if( is_armed() && weapon->is_gun() ) { - recoil += std::max( weapon->volume() / 250_ml - get_skill_level( skill_dodge ), 0 ) * rng( 0, 100 ); + if( is_armed() && weapon.is_gun() ) { + recoil += std::max( weapon.volume() / 250_ml - get_skill_level( skill_dodge ), 0 ) * rng( 0, 100 ); recoil = std::min( MAX_RECOIL, recoil ); } diff --git a/src/character.h b/src/character.h index 016c3847c3fa8..4f0538af92a17 100644 --- a/src/character.h +++ b/src/character.h @@ -2232,7 +2232,7 @@ class Character : public Creature, public visitable item weapon; public: const item &get_wielded_item() const; - item *get_wielded_item(); + item &get_wielded_item(); void set_wielded_item( const item &to_wield ); int scent = 0; diff --git a/src/crafting.cpp b/src/crafting.cpp index 17132add328e1..40d5ba953e9eb 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -640,14 +640,14 @@ static void set_components( std::list &components, const std::list & static cata::optional wield_craft( Character &p, item &craft ) { - item *weapon = p.get_wielded_item(); + item &weapon = p.get_wielded_item(); if( p.wield( craft ) ) { - if( weapon->invlet ) { - p.add_msg_if_player( m_info, _( "Wielding %c - %s" ), weapon->invlet, weapon->display_name() ); + if( weapon.invlet ) { + p.add_msg_if_player( m_info, _( "Wielding %c - %s" ), weapon.invlet, weapon.display_name() ); } else { - p.add_msg_if_player( m_info, _( "Wielding - %s" ), weapon->display_name() ); + p.add_msg_if_player( m_info, _( "Wielding - %s" ), weapon.display_name() ); } - return item_location( p, weapon ); + return item_location( p, &weapon ); } return cata::nullopt; } @@ -788,8 +788,8 @@ static item_location place_craft_or_disassembly( amenu.text = string_format( pgettext( "in progress craft", "What to do with the %s?" ), craft.display_name() ); - amenu.addentry( WIELD_CRAFT, ch.can_unwield( *ch.get_wielded_item() ).success(), - '1', _( "Dispose of your wielded %s and start working." ), ch.get_wielded_item()->tname() ); + amenu.addentry( WIELD_CRAFT, ch.can_unwield( ch.get_wielded_item() ).success(), + '1', _( "Dispose of your wielded %s and start working." ), ch.get_wielded_item().tname() ); amenu.addentry( DROP_CRAFT, true, '2', _( "Put it down and start working." ) ); const bool can_stash = ch.can_pickVolume( craft ) && ch.can_pickWeight( craft, !get_option( "DANGEROUS_PICKUPS" ) ); @@ -1719,7 +1719,7 @@ static void empty_buckets( Character &p ) { // First grab (remove) all items that are non-empty buckets and not wielded auto buckets = p.remove_items_with( [&p]( const item & it ) { - return it.is_bucket_nonempty() && &it != p.get_wielded_item(); + return it.is_bucket_nonempty() && &it != &p.get_wielded_item(); }, INT_MAX ); for( auto &it : buckets ) { for( const item *in : it.all_items_top() ) { diff --git a/src/debug_menu.cpp b/src/debug_menu.cpp index c14d5d1d641a8..96a5da7d874c4 100644 --- a/src/debug_menu.cpp +++ b/src/debug_menu.cpp @@ -1345,7 +1345,7 @@ static void character_edit_menu() } else if( !to_wear.is_null() ) { you.set_wielded_item( to_wear ); get_event_bus().send( you.getID(), - you.get_wielded_item()->typeId() ); + you.get_wielded_item().typeId() ); } } break; diff --git a/src/do_turn.cpp b/src/do_turn.cpp index a88b6b354cb4d..1d2e77f00c813 100644 --- a/src/do_turn.cpp +++ b/src/do_turn.cpp @@ -37,7 +37,6 @@ static const activity_id ACT_OPERATION( "ACT_OPERATION" ); static const activity_id ACT_AUTODRIVE( "ACT_AUTODRIVE" ); static const efftype_id effect_controlled( "controlled" ); -static const efftype_id effect_downed( "downed" ); static const efftype_id effect_npc_suspend( "npc_suspend" ); static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_sleep( "sleep" ); @@ -46,7 +45,6 @@ static const itype_id itype_holybook_bible1( "holybook_bible1" ); static const itype_id itype_holybook_bible2( "holybook_bible2" ); static const itype_id itype_holybook_bible3( "holybook_bible3" ); -static const trait_id trait_LEG_TENT_BRACE( "LEG_TENT_BRACE" ); static const trait_id trait_HAS_NEMESIS( "HAS_NEMESIS" ); #if defined(__ANDROID__) @@ -353,219 +351,6 @@ bool cleanup_at_end() return true; } -// TODO: abstract out the location checking code -// TODO: refactor so zombies can follow up and down stairs instead of this mess -void update_stair_monsters() -{ - // Search for the stairs closest to the player. - std::vector stairx; - std::vector stairy; - std::vector stairdist; - - map &m = get_map(); - const bool from_below = g->monstairz < m.get_abs_sub().z; - - if( g->coming_to_stairs.empty() ) { - return; - } - - if( m.has_zlevels() ) { - debugmsg( "%d monsters coming to stairs on a map with z-levels", - g->coming_to_stairs.size() ); - g->coming_to_stairs.clear(); - } - - avatar &u = get_avatar(); - for( const tripoint &dest : m.points_on_zlevel( u.posz() ) ) { - if( ( from_below && m.has_flag( ter_furn_flag::TFLAG_GOES_DOWN, dest ) ) || - ( !from_below && m.has_flag( ter_furn_flag::TFLAG_GOES_UP, dest ) ) ) { - stairx.push_back( dest.x ); - stairy.push_back( dest.y ); - stairdist.push_back( rl_dist( dest, u.pos() ) ); - } - } - if( stairdist.empty() ) { - return; // Found no stairs? - } - - // Find closest stairs. - size_t si = 0; - for( size_t i = 0; i < stairdist.size(); i++ ) { - if( stairdist[i] < stairdist[si] ) { - si = i; - } - } - - // Find up to 4 stairs for distance stairdist[si] +1 - std::vector nearest; - nearest.push_back( si ); - for( size_t i = 0; i < stairdist.size() && nearest.size() < 4; i++ ) { - if( ( i != si ) && ( stairdist[i] <= stairdist[si] + 1 ) ) { - nearest.push_back( i ); - } - } - // Randomize the stair choice - si = random_entry_ref( nearest ); - - creature_tracker &creatures = get_creature_tracker(); - // Attempt to spawn zombies. - for( size_t i = 0; i < g->coming_to_stairs.size(); i++ ) { - point mpos( stairx[si], stairy[si] ); - monster &critter = g->coming_to_stairs[i]; - const tripoint dest { - mpos, get_map().get_abs_sub().z - }; - - // We might be not be visible. - if( ( critter.posx() < 0 - ( MAPSIZE_X ) / 6 || - critter.posy() < 0 - ( MAPSIZE_Y ) / 6 || - critter.posx() > ( MAPSIZE_X * 7 ) / 6 || - critter.posy() > ( MAPSIZE_Y * 7 ) / 6 ) ) { - continue; - } - - critter.staircount -= 4; - // Let the player know zombies are trying to come. - if( u.sees( dest ) ) { - std::string dump; - if( critter.staircount > 4 ) { - dump += string_format( _( "You see a %s on the stairs" ), critter.name() ); - } else { - if( critter.staircount > 0 ) { - dump += ( from_below ? - //~ The is almost at the of the ! - string_format( _( "The %1$s is almost at the top of the %2$s!" ), - critter.name(), - m.tername( dest ) ) : - string_format( _( "The %1$s is almost at the bottom of the %2$s!" ), - critter.name(), - m.tername( dest ) ) ); - } - } - - add_msg( m_warning, dump ); - } else { - sounds::sound( dest, 5, sounds::sound_t::movement, - _( "a sound nearby from the stairs!" ), true, "misc", "stairs_movement" ); - } - - if( critter.staircount > 0 ) { - continue; - } - - if( g->is_empty( dest ) ) { - critter.spawn( dest ); - critter.staircount = 0; - g->place_critter_at( make_shared_fast( critter ), dest ); - if( u.sees( dest ) ) { - if( !from_below ) { - add_msg( m_warning, _( "The %1$s comes down the %2$s!" ), - critter.name(), - m.tername( dest ) ); - } else { - add_msg( m_warning, _( "The %1$s comes up the %2$s!" ), - critter.name(), - m.tername( dest ) ); - } - } - g->coming_to_stairs.erase( g->coming_to_stairs.begin() + i ); - continue; - } else if( u.pos() == dest ) { - // Monster attempts to push player of stairs - point push( point_north_west ); - int tries = 0; - - // the critter is now right on top of you and will attack unless - // it can find a square to push you into with one of his tries. - const int creature_push_attempts = 9; - const int player_throw_resist_chance = 3; - - critter.spawn( dest ); - while( tries < creature_push_attempts ) { - tries++; - push.x = rng( -1, 1 ); - push.y = rng( -1, 1 ); - point ipos( mpos + push ); - tripoint pos( ipos, m.get_abs_sub().z ); - if( ( push.x != 0 || push.y != 0 ) && !creatures.creature_at( pos ) && - critter.can_move_to( pos ) ) { - bool resiststhrow = ( u.is_throw_immune() ) || - ( u.has_trait( trait_LEG_TENT_BRACE ) ); - if( resiststhrow && one_in( player_throw_resist_chance ) ) { - u.moves -= 25; // small charge for avoiding the push altogether - add_msg( _( "The %s fails to push you back!" ), - critter.name() ); - return; //judo or leg brace prevent you from getting pushed at all - } - // Not accounting for tentacles latching on, so.. - // Something is about to happen, lets charge half a move - u.moves -= 50; - if( resiststhrow && ( u.is_throw_immune() ) ) { - //we have a judoka who isn't getting pushed but counterattacking now. - mattack::thrown_by_judo( &critter ); - return; - } - std::string msg; - ///\EFFECT_DODGE reduces chance of being downed when pushed off the stairs - if( !( resiststhrow ) && ( u.get_dodge() + rng( 0, 3 ) < 12 ) ) { - // dodge 12 - never get downed - // 11.. avoid 75%; 10.. avoid 50%; 9.. avoid 25% - u.add_effect( effect_downed, 2_turns ); - msg = _( "The %s pushed you back hard!" ); - } else { - msg = _( "The %s pushed you back!" ); - } - add_msg( m_warning, msg.c_str(), critter.name() ); - u.move_to( u.get_location() + push ); - return; - } - } - add_msg( m_warning, - _( "The %s tried to push you back but failed! It attacks you!" ), - critter.name() ); - critter.melee_attack( u ); - u.moves -= 50; - return; - } else if( monster *const mon_ptr = creatures.creature_at( dest ) ) { - // Monster attempts to displace a monster from the stairs - monster &other = *mon_ptr; - critter.spawn( dest ); - - // the critter is now right on top of another and will push it - // if it can find a square to push it into inside of his tries. - const int creature_push_attempts = 9; - const int creature_throw_resist = 4; - - int tries = 0; - point push2; - while( tries < creature_push_attempts ) { - tries++; - push2.x = rng( -1, 1 ); - push2.y = rng( -1, 1 ); - point ipos2( mpos + push2 ); - tripoint pos( ipos2, m.get_abs_sub().z ); - if( ( push2.x == 0 && push2.y == 0 ) || ( ( ipos2.x == u.posx() ) && ( ipos2.y == u.posy() ) ) ) { - continue; - } - if( !creatures.creature_at( pos ) && other.can_move_to( pos ) ) { - other.setpos( tripoint( ipos2, m.get_abs_sub().z ) ); - other.moves -= 50; - std::string msg; - if( one_in( creature_throw_resist ) ) { - other.add_effect( effect_downed, 2_turns ); - msg = _( "The %1$s pushed the %2$s hard." ); - } else { - msg = _( "The %1$s pushed the %2$s." ); - } - add_msg( m_neutral, msg, critter.name(), other.name() ); - return; - } - } - return; - } - } -} - } // namespace turn_handler void handle_key_blocking_activity() @@ -996,7 +781,6 @@ bool do_turn() } } } - turn_handler::update_stair_monsters(); g->mon_info_update(); u.process_turn(); if( u.moves < 0 && get_option( "FORCE_REDRAW" ) ) { diff --git a/src/editmap.cpp b/src/editmap.cpp index b3511e2151981..c7fac0d52f1f1 100644 --- a/src/editmap.cpp +++ b/src/editmap.cpp @@ -661,7 +661,7 @@ void editmap::draw_main_ui_overlay() g->draw_vpart_override( map_p, vpart_id::NULL_ID(), 0, 0_degrees, false, point_zero ); } - g->draw_below_override( map_p, here.has_zlevels() && + g->draw_below_override( map_p, tmpmap.ter( tmp_p ).obj().has_flag( ter_furn_flag::TFLAG_NO_FLOOR ) ); } } diff --git a/src/effect.cpp b/src/effect.cpp index 358abe16ebcc8..44968b9a8a739 100644 --- a/src/effect.cpp +++ b/src/effect.cpp @@ -1494,7 +1494,7 @@ void load_effect_type( const JsonObject &jo ) new_etype.int_add_val = jo.get_int( "int_add_val", 0 ); new_etype.int_decay_step = jo.get_int( "int_decay_step", -1 ); new_etype.int_decay_tick = jo.get_int( "int_decay_tick", 0 ); - optional( jo, false, "int_decay_remove", new_etype.int_decay_remove, true ); + optional( jo, false, "int_decay_remove", new_etype.int_decay_remove, false ); new_etype.load_miss_msgs( jo, "miss_messages" ); new_etype.load_decay_msgs( jo, "decay_messages" ); diff --git a/src/effect.h b/src/effect.h index 2bd714b4cae68..ac7622016ca73 100644 --- a/src/effect.h +++ b/src/effect.h @@ -139,7 +139,7 @@ class effect_type int int_decay_step = 0; int int_decay_tick = 0 ; time_duration int_dur_factor = 0_turns; - bool int_decay_remove = true; + bool int_decay_remove = false; std::set flags; diff --git a/src/explosion.cpp b/src/explosion.cpp index bc880364c0862..7cc415a388960 100644 --- a/src/explosion.cpp +++ b/src/explosion.cpp @@ -166,7 +166,7 @@ static void do_blast( const tripoint &p, const float power, static const int y_offset[10] = { 0, 0, -1, 1, -1, 1, -1, 1, 0, 0 }; static const int z_offset[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 }; map &here = get_map(); - const size_t max_index = here.has_zlevels() ? 10 : 8; + const size_t max_index = 10; here.bash( p, fire ? power : ( 2 * power ), true, false, false ); @@ -292,13 +292,6 @@ static void do_blast( const tripoint &p, const float power, if( force > 10.0f || x_in_y( force, 10.0f ) ) { intensity++; } - - if( !here.has_zlevels() && here.is_outside( pt ) && intensity == 2 ) { - // In 3D mode, it would have fire fields above, which would then fall - // and fuel the fire on this tile - intensity++; - } - here.add_field( pt, fd_fire, intensity ); } @@ -774,13 +767,13 @@ void emp_blast( const tripoint &p ) } // TODO: More effects? //e-handcuffs effects - item *weapon = player_character.get_wielded_item(); - if( weapon->typeId() == itype_e_handcuffs && weapon->charges > 0 ) { - weapon->unset_flag( STATIC( flag_id( "NO_UNWIELD" ) ) ); - weapon->charges = 0; - weapon->active = false; + item &weapon = player_character.get_wielded_item(); + if( weapon.typeId() == itype_e_handcuffs && weapon.charges > 0 ) { + weapon.unset_flag( STATIC( flag_id( "NO_UNWIELD" ) ) ); + weapon.charges = 0; + weapon.active = false; add_msg( m_good, _( "The %s on your wrists spark briefly, then release your hands!" ), - weapon->tname() ); + weapon.tname() ); } } // Drain any items of their battery charge diff --git a/src/game.cpp b/src/game.cpp index 2d230e3f981c6..a2e454ec326ee 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -196,7 +196,6 @@ static constexpr int DANGEROUS_PROXIMITY = 5; static const mtype_id mon_manhack( "mon_manhack" ); -static const skill_id skill_melee( "melee" ); static const skill_id skill_dodge( "dodge" ); static const skill_id skill_gun( "gun" ); static const skill_id skill_firstaid( "firstaid" ); @@ -610,7 +609,7 @@ void game::setup() load_world_modfiles( ui ); - m = map( true ); + m = map(); next_npc_id = character_id( 1 ); next_mission_id = 1; @@ -632,7 +631,6 @@ void game::setup() sounds::reset_sounds(); clear_zombies(); - coming_to_stairs.clear(); critter_tracker->clear_npcs(); faction_manager_ptr->clear(); mission::clear_all(); @@ -959,7 +957,7 @@ void game::load_npcs() const tripoint_abs_sm sm_loc = temp->global_sm_location(); // NPCs who are out of bounds before placement would be pushed into bounds // This can cause NPCs to teleport around, so we don't want that - if( !map_bounds.contains( sm_loc.xy() ) || ( sm_loc.z() != abs_sub.z() && !m.has_zlevels() ) ) { + if( !map_bounds.contains( sm_loc.xy() ) ) { continue; } @@ -1662,7 +1660,7 @@ int game::inventory_item_menu( item_location locThisItem, std::vector vDummy; const bool bHPR = get_auto_pickup().has_rule( &oThisItem ); - const hint_rating rate_drop_item = u.get_wielded_item()->has_flag( flag_NO_UNWIELD ) ? + const hint_rating rate_drop_item = u.get_wielded_item().has_flag( flag_NO_UNWIELD ) ? hint_rating::cant : hint_rating::good; @@ -2274,7 +2272,7 @@ bool game::try_get_right_click_action( action_id &act, const tripoint &mouse_tar return false; } - if( !u.get_wielded_item()->is_gun() ) { + if( !u.get_wielded_item().is_gun() ) { add_msg( m_info, _( "You are not wielding a ranged weapon." ) ); return false; } @@ -3210,7 +3208,7 @@ void game::draw_critter( const Creature &critter, const tripoint ¢er ) if( !is_valid_in_w_terrain( point( mx, my ) ) ) { return; } - if( critter.posz() != center.z && m.has_zlevels() ) { + if( critter.posz() != center.z ) { static constexpr tripoint up_tripoint( tripoint_above ); if( critter.posz() == center.z - 1 && ( debug_mode || u.sees( critter ) ) && @@ -5701,7 +5699,7 @@ void game::print_terrain_info( const tripoint &lp, const catacurses::window &w_l mvwprintz( w_look, point( column + utf8_width( _( "Lighting: " ) ), line ), ll.second, ll.first ); // Print the terrain and any furntiure on the tile below and whether it is walkable. - if( m.has_zlevels() && lp.z > -OVERMAP_DEPTH && !m.has_floor( lp ) ) { + if( lp.z > -OVERMAP_DEPTH && !m.has_floor( lp ) ) { tripoint below( lp.xy(), lp.z - 1 ); std::string tile_below = m.tername( below ); if( m.has_furn( below ) ) { @@ -6396,7 +6394,7 @@ look_around_result game::look_around( const bool show_window, tripoint ¢er, { bVMonsterLookFire = false; // TODO: Make this `true` - const bool allow_zlev_move = m.has_zlevels() && get_option( "FOV_3D" ); + const bool allow_zlev_move = get_option( "FOV_3D" ); temp_exit_fullscreen(); @@ -6711,7 +6709,7 @@ look_around_result game::look_around( const bool show_window, tripoint ¢er, } while( action != "QUIT" && action != "CONFIRM" && action != "SELECT" && action != "TRAVEL_TO" && action != "throw_blind" ); - if( m.has_zlevels() && center.z != old_levz ) { + if( center.z != old_levz ) { m.invalidate_map_cache( old_levz ); m.build_map_cache( old_levz ); u.view_offset.z = 0; @@ -7569,7 +7567,7 @@ game::vmenu_ret game::list_monsters( const std::vector &monster_list } ); ui.mark_resize(); - const int max_gun_range = u.get_wielded_item()->gun_range( &u ); + const int max_gun_range = u.get_wielded_item().gun_range( &u ); const tripoint stored_view_offset = u.view_offset; u.view_offset = tripoint_zero; @@ -8549,12 +8547,12 @@ void game::reload_item() void game::reload_wielded( bool prompt ) { - item *weapon = u.get_wielded_item(); - if( weapon->is_null() || !weapon->is_reloadable() ) { + item &weapon = u.get_wielded_item(); + if( weapon.is_null() || !weapon.is_reloadable() ) { add_msg( _( "You aren't holding something you can reload." ) ); return; } - item_location item_loc = item_location( u, weapon ); + item_location item_loc = item_location( u, &weapon ); reload( item_loc, prompt ); } @@ -8580,9 +8578,9 @@ void game::reload_weapon( bool try_everything ) return true; } // Second sort by affiliation with wielded gun - const std::set compatible_magazines = this->u.get_wielded_item()->magazine_compatible(); - const bool mag_ap = this->u.get_wielded_item()->can_contain( *ap, true ).success(); - const bool mag_bp = this->u.get_wielded_item()->can_contain( *bp, true ).success(); + const std::set compatible_magazines = this->u.get_wielded_item().magazine_compatible(); + const bool mag_ap = this->u.get_wielded_item().can_contain( *ap, true ).success(); + const bool mag_bp = this->u.get_wielded_item().can_contain( *bp, true ).success(); if( mag_ap != mag_bp ) { return mag_ap; } @@ -8630,8 +8628,8 @@ void game::wield( item_location loc ) debugmsg( "ERROR: tried to wield null item" ); return; } - const item *weapon = u.get_wielded_item(); - if( weapon != &*loc && weapon->has_item( *loc ) ) { + const item &weapon = u.get_wielded_item(); + if( &weapon != &*loc && weapon.has_item( *loc ) ) { add_msg( m_info, _( "You need to put the bag away before trying to wield something from it." ) ); return; } @@ -8917,8 +8915,7 @@ std::vector game::get_dangerous_tile( const tripoint &dest_loc ) co const trap &tr = m.tr_at( dest_loc ); // HACK: Hack for now, later ledge should stop being a trap - // Note: in non-z-level mode, ledges obey different rules and so should be handled as regular traps - if( tr == tr_ledge && m.has_zlevels() ) { + if( tr == tr_ledge ) { if( !veh_dest ) { harmful_stuff.emplace_back( tr.name() ); } @@ -9402,7 +9399,7 @@ point game::place_player( const tripoint &dest_loc ) } // Move the player // Start with z-level, to make it less likely that old functions (2D ones) freak out - if( m.has_zlevels() && dest_loc.z != m.get_abs_sub().z ) { + if( dest_loc.z != m.get_abs_sub().z ) { vertical_shift( dest_loc.z ); } @@ -9637,9 +9634,7 @@ void game::place_player_overmap( const tripoint_abs_omt &om_dest ) if( u.in_vehicle ) { m.unboard_vehicle( u.pos() ); } - const int minz = m.has_zlevels() ? -OVERMAP_DEPTH : m.get_abs_sub().z; - const int maxz = m.has_zlevels() ? OVERMAP_HEIGHT : m.get_abs_sub().z; - for( int z = minz; z <= maxz; z++ ) { + for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) { m.clear_vehicle_list( z ); } m.rebuild_vehicle_level_caches(); @@ -10353,8 +10348,7 @@ void game::vertical_move( int movez, bool force, bool peeking ) bool climbing = false; int move_cost = 100; tripoint stairs( u.posx(), u.posy(), u.posz() + movez ); - if( here.has_zlevels() && !force && movez == 1 && - !here.has_flag( ter_furn_flag::TFLAG_GOES_UP, u.pos() ) ) { + if( !force && movez == 1 && !here.has_flag( ter_furn_flag::TFLAG_GOES_UP, u.pos() ) ) { // Climbing if( here.has_floor_or_support( stairs ) ) { add_msg( m_info, _( "You can't climb here - there's a ceiling above your head." ) ); @@ -10411,10 +10405,7 @@ void game::vertical_move( int movez, bool force, bool peeking ) return; } - // Because abs_sub will change when vertical_shift (here.has_zlevels() == true) - // is called or when the map is loaded on new z-level (== false). - // This caches the z-level we start the movement on (current) and the level we're want to end. - const int z_before = m.get_abs_sub().z; + // TODO: Use u.posz() instead of m.abs_sub const int z_after = m.get_abs_sub().z + movez; if( z_after < -OVERMAP_DEPTH || z_after > OVERMAP_HEIGHT ) { debugmsg( "Tried to move outside allowed range of z-levels" ); @@ -10433,124 +10424,25 @@ void game::vertical_move( int movez, bool force, bool peeking ) } } - // Check if there are monsters are using the stairs. - bool slippedpast = false; - if( !here.has_zlevels() && !coming_to_stairs.empty() && !force ) { - // TODO: Allow travel if zombie couldn't reach stairs, but spawn him when we go up. - add_msg( m_warning, _( "You try to use the stairs. Suddenly you are blocked by a %s!" ), - coming_to_stairs[0].name() ); - // Roll. - ///\EFFECT_DEX increases chance of moving past monsters on stairs - - ///\EFFECT_DODGE increases chance of moving past monsters on stairs - int dexroll = dice( 6, u.dex_cur + u.get_skill_level( skill_dodge ) * 2 ); - ///\EFFECT_STR increases chance of moving past monsters on stairs - - ///\EFFECT_MELEE increases chance of moving past monsters on stairs - int strroll = dice( 3, u.str_cur + u.get_skill_level( skill_melee ) * 1.5 ); - if( coming_to_stairs.size() > 4 ) { - add_msg( _( "The are a lot of them on the %s!" ), here.tername( u.pos() ) ); - dexroll /= 4; - strroll /= 2; - } else if( coming_to_stairs.size() > 1 ) { - add_msg( m_warning, _( "There's something else behind it!" ) ); - dexroll /= 2; - } - - if( dexroll < 14 || strroll < 12 ) { - turn_handler::update_stair_monsters(); - u.moves -= 100; - return; - } - - add_msg( _( "You manage to slip past!" ) ); - slippedpast = true; - u.moves -= 100; - } - - // Shift the map up or down - - std::unique_ptr tmp_map_ptr; - if( !here.has_zlevels() ) { - tmp_map_ptr = std::make_unique(); - } - - map &maybetmp = here.has_zlevels() ? m : *( tmp_map_ptr.get() ); - if( here.has_zlevels() ) { - // We no longer need to shift the map here! What joy - } else { - // TODO: fix point types - maybetmp.load( tripoint_abs_sm( point_abs_sm( here.get_abs_sub().xy() ), z_after ), false ); - } - // Find the corresponding staircase bool rope_ladder = false; // TODO: Remove the stairfinding, make the mapgen gen aligned maps if( !force && !climbing ) { - const cata::optional pnt = find_or_make_stairs( maybetmp, z_after, rope_ladder, peeking ); + const cata::optional pnt = find_or_make_stairs( m, z_after, rope_ladder, peeking ); if( !pnt ) { return; } stairs = *pnt; } - if( !force ) { - monstairz = z_before; - } - // Save all monsters that can reach the stairs, remove them from the tracker, - // then despawn the remaining monsters. Because it's a vertical shift, all - // monsters are out of the bounds of the map and will despawn. - shared_ptr_fast stored_mount; - if( u.is_mounted() && !here.has_zlevels() ) { - // Store a *copy* of the mount, so we can remove the original monster instance - // from the tracker before the map shifts. - // Map shifting would otherwise just despawn the mount and would later respawn it. - stored_mount = make_shared_fast( *u.mounted_creature ); - critter_tracker->remove( *u.mounted_creature ); - } - if( !here.has_zlevels() ) { - const tripoint to = u.pos(); - for( monster &critter : all_monsters() ) { - // if its a ladder instead of stairs - most zombies can't climb that. - // unless that have a special flag to allow them to do so. - if( ( here.has_flag( ter_furn_flag::TFLAG_DIFFICULT_Z, u.pos() ) && !critter.climbs() ) || - critter.has_effect( effect_ridden ) || - critter.has_effect( effect_tied ) ) { - continue; - } - int turns = critter.turns_to_reach( to.xy() ); - if( turns < 10 && coming_to_stairs.size() < 8 && critter.will_reach( to.xy() ) - && !slippedpast ) { - critter.staircount = 10 + turns; - critter.on_unload(); - coming_to_stairs.push_back( critter ); - remove_zombie( critter ); - } - } - auto mons = critter_tracker->find( u.get_location() ); - if( mons != nullptr ) { - critter_tracker->remove( *mons ); - } - shift_monsters( tripoint( 0, 0, movez ) ); - } - - std::vector> npcs_to_bring; std::vector monsters_following; - if( !here.has_zlevels() && std::abs( movez ) == 1 ) { - std::copy_if( critter_tracker->active_npc.begin(), critter_tracker->active_npc.end(), - back_inserter( npcs_to_bring ), - [this]( const shared_ptr_fast &np ) { - return np->is_walking_with() && !np->is_mounted() && !np->in_sleep_state() && - rl_dist( np->pos(), u.pos() ) < 2; - } ); - } - - if( here.has_zlevels() && std::abs( movez ) == 1 ) { + if( std::abs( movez ) == 1 ) { bool ladder = here.has_flag( ter_furn_flag::TFLAG_DIFFICULT_Z, u.pos() ); for( monster &critter : all_monsters() ) { if( ladder && !critter.climbs() ) { continue; } + // TODO: just check if it's going for the avatar's location, it's simpler Creature *target = critter.attack_target(); if( ( target && target->is_avatar() ) || ( !critter.has_effect( effect_ridden ) && critter.has_effect( effect_pet ) && critter.friendly == -1 && @@ -10568,11 +10460,6 @@ void game::vertical_move( int movez, bool force, bool peeking ) } else { u.moves -= move_cost; } - for( const auto &np : npcs_to_bring ) { - if( np->in_vehicle ) { - here.unboard_vehicle( np->pos() ); - } - } const tripoint old_pos = u.pos(); const tripoint old_abs_pos = here.getabs( old_pos ); point submap_shift; @@ -10632,46 +10519,7 @@ void game::vertical_move( int movez, bool force, bool peeking ) // Now that we know the player's destination position, we can move their mount as well if( u.is_mounted() ) { - if( stored_mount ) { - cata_assert( !here.has_zlevels() ); - stored_mount->spawn( u.get_location() ); - if( critter_tracker->add( stored_mount ) ) { - u.mounted_creature = stored_mount; - } - } else { - u.mounted_creature->setpos( u.pos() ); - } - } - - if( !npcs_to_bring.empty() ) { - // Would look nicer randomly scrambled - std::vector candidates = closest_points_first( u.pos(), 1 ); - candidates.erase( std::remove_if( candidates.begin(), candidates.end(), - [this]( const tripoint & c ) { - return !is_empty( c ); - } ), candidates.end() ); - - for( const auto &np : npcs_to_bring ) { - const auto found = std::find_if( candidates.begin(), candidates.end(), - [np, &here]( const tripoint & c ) { - // @TODO NPC should appear on top of invisible traps (and trigger them), - // instead of magically choosing tiles without dangerous traps. - return !np->is_dangerous_fields( here.field_at( c ) ) && here.tr_at( c ).is_benign(); - } ); - if( found != candidates.end() ) { - // TODO: De-uglify - np->setpos( *found ); - np->place_on_map(); - np->setpos( *found ); - candidates.erase( found ); - } - - if( candidates.empty() ) { - break; - } - } - - reload_npcs(); + u.mounted_creature->setpos( u.pos() ); } // This ugly check is here because of stair teleport bullshit @@ -10691,12 +10539,6 @@ void game::vertical_move( int movez, bool force, bool peeking ) here.ter_set( stairs, t_manhole ); } - // Wouldn't work and may do strange things - if( u.is_hauling() && !here.has_zlevels() ) { - add_msg( _( "You cannot haul items here." ) ); - u.stop_hauling(); - } - if( u.is_hauling() ) { const tripoint adjusted_pos = old_pos - sm_to_ms_copy( submap_shift ); start_hauling( adjusted_pos ); @@ -10897,32 +10739,14 @@ void game::vertical_shift( const int z_after ) // TODO: Implement dragging stuff up/down u.grab( object_type::NONE ); - scent.reset(); + const int z_before = u.posz(); u.move_to( tripoint_abs_ms( u.get_location().xy(), z_after ) ); - const tripoint abs_sub = m.get_abs_sub(); - const int z_before = abs_sub.z; - if( !m.has_zlevels() ) { - m.access_cache( z_before ).vehicle_list.clear(); - m.access_cache( z_before ).zone_vehicles.clear(); - m.access_cache( z_before ).map_memory_seen_cache.reset(); - m.set_transparency_cache_dirty( z_before ); - m.set_outside_cache_dirty( z_before ); - // TODO: fix point types - m.load( tripoint_abs_sm( point_abs_sm( abs_sub.xy() ), z_after ), true ); - shift_monsters( tripoint( 0, 0, z_after - z_before ) ); - reload_npcs(); - m.rebuild_vehicle_level_caches(); - } else { - // Shift the map itself - m.vertical_shift( z_after ); - } - m.spawn_monsters( true ); - // this may be required after a vertical shift if z-levels are not enabled - // the critter is unloaded/loaded, and it needs to reconstruct its rider data after being reloaded. - validate_mounted_npcs(); + // Shift the map itself + m.vertical_shift( z_after ); + vertical_notes( z_before, z_after ); } @@ -11046,12 +10870,8 @@ point game::update_map( int &x, int &y ) load_npcs(); // Make sure map cache is consistent since it may have shifted. - if( m.has_zlevels() ) { - for( int zlev = -OVERMAP_DEPTH; zlev <= OVERMAP_HEIGHT; ++zlev ) { - m.invalidate_map_cache( zlev ); - } - } else { - m.invalidate_map_cache( m.get_abs_sub().z ); + for( int zlev = -OVERMAP_DEPTH; zlev <= OVERMAP_HEIGHT; ++zlev ) { + m.invalidate_map_cache( zlev ); } m.build_map_cache( m.get_abs_sub().z ); @@ -11120,7 +10940,6 @@ void game::despawn_monster( monster &critter ) void game::shift_monsters( const tripoint &shift ) { - // If either shift argument is non-zero, we're shifting. if( shift == tripoint_zero ) { return; } @@ -11129,13 +10948,11 @@ void game::shift_monsters( const tripoint &shift ) critter.shift( shift.xy() ); } - if( m.inbounds( critter.pos() ) && ( shift.z == 0 || m.has_zlevels() ) ) { + if( m.inbounds( critter.pos() ) ) { // We're inbounds, so don't despawn after all. - // No need to shift Z-coordinates, they are absolute continue; } - // Either a vertical shift or the critter is now outside of the reality bubble, - // anyway: it must be saved and removed. + // The critter is now outside of the reality bubble; it must be saved and removed. despawn_monster( critter ); } } diff --git a/src/game.h b/src/game.h index 90b521803ac65..35a6125ab0527 100644 --- a/src/game.h +++ b/src/game.h @@ -137,7 +137,6 @@ bool is_valid_in_w_terrain( const point &p ); namespace turn_handler { bool cleanup_at_end(); -void update_stair_monsters(); } // namespace turn_handler // There is only one game instance, so losing a few bytes of memory @@ -1001,9 +1000,6 @@ class game /** True if the game has just started or loaded, else false. */ bool new_game = false; // NOLINT(cata-serialize) - std::vector coming_to_stairs; - int monstairz = 0; - tripoint ter_view_p; // NOLINT(cata-serialize) catacurses::window w_terrain; // NOLINT(cata-serialize) catacurses::window w_overmap; // NOLINT(cata-serialize) diff --git a/src/gamemode_tutorial.cpp b/src/gamemode_tutorial.cpp index 4500af8416c83..0528515ec6710 100644 --- a/src/gamemode_tutorial.cpp +++ b/src/gamemode_tutorial.cpp @@ -192,11 +192,11 @@ void tutorial_game::per_turn() } } - if( !player_character.get_wielded_item()->is_null() ) { + if( !player_character.get_wielded_item().is_null() ) { add_message( tut_lesson::LESSON_WIELD_NO_SPACE ); } - if( player_character.get_wielded_item()->ammo_remaining( &player_character ) > 0 ) { + if( player_character.get_wielded_item().ammo_remaining( &player_character ) > 0 ) { add_message( tut_lesson::LESSON_GUN_FIRE ); } @@ -308,7 +308,7 @@ void tutorial_game::post_action( action_id act ) break; case ACTION_FIRE: - if( player_character.get_wielded_item()->is_gun() ) { + if( player_character.get_wielded_item().is_gun() ) { add_message( tut_lesson::LESSON_RECOIL ); } break; diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 4789a1b10b017..3cb49a3120065 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -461,10 +461,6 @@ static void pldrive( const tripoint &p ) player_character.add_msg_if_player( m_info, _( "This vehicle doesn't look very airworthy." ) ); return; } - if( !here.has_zlevels() ) { - player_character.add_msg_if_player( m_info, _( "This vehicle cannot be flown without z levels." ) ); - return; - } } if( p.z == -1 ) { if( veh->check_heli_descend( player_character ) ) { @@ -665,7 +661,7 @@ static void smash() } } const int move_cost = !player_character.is_armed() ? 80 : - player_character.get_wielded_item()->attack_time() * + player_character.get_wielded_item().attack_time() * 0.8; bool didit = false; bool mech_smash = false; @@ -677,7 +673,7 @@ static void smash() mon->type->melee_sides; mech_smash = true; } else { - smashskill = player_character.str_cur + player_character.get_wielded_item()->damage_melee( + smashskill = player_character.str_cur + player_character.get_wielded_item().damage_melee( damage_type::BASH ); } @@ -799,11 +795,11 @@ static void smash() didit = here.bash( smashp, smashskill, false, false, smash_floor ).did_bash; // Weariness scaling float weary_mult = 1.0f; - item *weapon = player_character.get_wielded_item(); + item &weapon = player_character.get_wielded_item(); if( didit ) { if( !mech_smash ) { player_character.set_activity_level( MODERATE_EXERCISE ); - player_character.handle_melee_wear( *weapon ); + player_character.handle_melee_wear( weapon ); weary_mult = 1.0f / player_character.exertion_adjusted_move_multiplier( MODERATE_EXERCISE ); const int mod_sta = 2 * player_character.get_standard_stamina_cost(); @@ -812,11 +808,11 @@ static void smash() if( player_character.get_skill_level( skill_melee ) == 0 ) { player_character.practice( skill_melee, rng( 0, 1 ) * rng( 0, 1 ) ); } - const int vol = weapon->volume() / units::legacy_volume_factor; - if( weapon->made_of( material_id( "glass" ) ) && + const int vol = weapon.volume() / units::legacy_volume_factor; + if( weapon.made_of( material_id( "glass" ) ) && rng( 0, vol + 3 ) < vol ) { - add_msg( m_bad, _( "Your %s shatters!" ), weapon->tname() ); - weapon->spill_contents( player_character.pos() ); + add_msg( m_bad, _( "Your %s shatters!" ), weapon.tname() ); + weapon.spill_contents( player_character.pos() ); sounds::sound( player_character.pos(), 24, sounds::sound_t::combat, "CRACK!", true, "smash", "glass" ); player_character.deal_damage( nullptr, bodypart_id( "hand_r" ), damage_instance( damage_type::CUT, @@ -1331,7 +1327,7 @@ static void reach_attack( avatar &you ) { g->temp_exit_fullscreen(); - target_handler::trajectory traj = target_handler::mode_reach( you, *you.get_wielded_item() ); + target_handler::trajectory traj = target_handler::mode_reach( you, you.get_wielded_item() ); if( !traj.empty() ) { you.reach_attack( traj.back() ); @@ -1393,10 +1389,10 @@ static void fire() } } } - const item *weapon = player_character.get_wielded_item(); - if( weapon->is_gun() && !weapon->gun_current_mode().melee() ) { + const item &weapon = player_character.get_wielded_item(); + if( weapon.is_gun() && !weapon.gun_current_mode().melee() ) { avatar_action::fire_wielded_weapon( player_character ); - } else if( weapon->current_reach_range( player_character ) > 1 ) { + } else if( weapon.current_reach_range( player_character ) > 1 ) { if( player_character.has_effect( effect_relax_gas ) ) { if( one_in( 8 ) ) { add_msg( m_good, _( "Your willpower asserts itself, and so do you!" ) ); @@ -1483,7 +1479,7 @@ bool Character::cast_spell( spell &sp, bool fake_spell, const cata::optional target = cata::nullopt ) { if( is_armed() && !sp.has_flag( spell_flag::NO_HANDS ) && - !get_wielded_item()->has_flag( flag_MAGIC_FOCUS ) && !sp.check_if_component_in_hand( *this ) ) { + !get_wielded_item().has_flag( flag_MAGIC_FOCUS ) && !sp.check_if_component_in_hand( *this ) ) { add_msg( game_message_params{ m_bad, gmf_bypass_cooldown }, _( "You need your hands free to cast this spell!" ) ); return false; @@ -1762,7 +1758,7 @@ static void do_deathcam_action( const action_id &act, avatar &player_character ) bool game::do_regular_action( action_id &act, avatar &player_character, const cata::optional &mouse_target ) { - item *weapon = player_character.get_wielded_item(); + item &weapon = player_character.get_wielded_item(); switch( act ) { case ACTION_NULL: // dummy entry case NUM_ACTIONS: // dummy entry @@ -2128,22 +2124,22 @@ bool game::do_regular_action( action_id &act, avatar &player_character, break; case ACTION_FIRE_BURST: { - gun_mode_id original_mode = weapon->gun_get_mode_id(); - if( weapon->gun_set_mode( gun_mode_id( "AUTO" ) ) ) { + gun_mode_id original_mode = weapon.gun_get_mode_id(); + if( weapon.gun_set_mode( gun_mode_id( "AUTO" ) ) ) { avatar_action::fire_wielded_weapon( player_character ); - weapon->gun_set_mode( original_mode ); + weapon.gun_set_mode( original_mode ); } break; } case ACTION_SELECT_FIRE_MODE: if( player_character.is_armed() ) { - if( weapon->is_gun() && !weapon->is_gunmod() && - weapon->gun_all_modes().size() > 1 ) { - weapon->gun_cycle_mode(); - } else if( weapon->has_flag( flag_RELOAD_ONE ) || - weapon->has_flag( flag_RELOAD_AND_SHOOT ) ) { - item::reload_option opt = player_character.select_ammo( *weapon, false ); + if( weapon.is_gun() && !weapon.is_gunmod() && + weapon.gun_all_modes().size() > 1 ) { + weapon.gun_cycle_mode(); + } else if( weapon.has_flag( flag_RELOAD_ONE ) || + weapon.has_flag( flag_RELOAD_AND_SHOOT ) ) { + item::reload_option opt = player_character.select_ammo( weapon, false ); if( !opt ) { break; } else if( player_character.ammo_location && opt.ammo == player_character.ammo_location ) { diff --git a/src/iexamine.cpp b/src/iexamine.cpp index c88d95267afd2..b595a31644e77 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -227,6 +227,13 @@ bool iexamine::always_false( const tripoint &/*examp*/ ) return false; } +bool iexamine::false_and_debugmsg( const tripoint &examp ) +{ + debugmsg( "Called false_and_debugmsg on %s - was a terrain with an actor configured incorrectly?", + get_map().tername( examp ) ); + return false; +} + bool iexamine::always_true( const tripoint &/*examp*/ ) { return true; @@ -4562,11 +4569,6 @@ void iexamine::ledge( Character &you, const tripoint &examp ) break; } case 2: { - if( !here.has_zlevels() ) { - // No climbing down in 2D mode - return; - } - if( !here.valid_move( you.pos(), examp, false, true ) ) { // Covered with something return; @@ -6227,6 +6229,11 @@ void iexamine::workout( Character &you, const tripoint &examp ) you.assign_activity( player_activity( workout_activity_actor( examp ) ) ); } +void iexamine::invalid( Character &/*you*/, const tripoint &examp ) +{ + debugmsg( "Called invalid iexamine function on %s!", get_map().tername( examp ) ); +} + /** * Given then name of one of the above functions, returns the matching function * pointer. If no match is found, defaults to iexamine::none but prints out a @@ -6313,7 +6320,8 @@ iexamine_functions iexamine_functions_from_string( const std::string &function_n { "smoker_options", &iexamine::smoker_options }, { "open_safe", &iexamine::open_safe }, { "workbench", &iexamine::workbench }, - { "workout", &iexamine::workout } + { "workout", &iexamine::workout }, + { "invalid", &iexamine::invalid }, } }; @@ -6330,6 +6338,8 @@ iexamine_functions iexamine_functions_from_string( const std::string &function_n iexamine_examine_function func = iter->second; if( function_name == "none" ) { return iexamine_functions{&iexamine::always_false, func}; + } else if( function_name == "invalid" ) { + return iexamine_functions{&iexamine::false_and_debugmsg, func}; } else if( harvestable_functions.find( function_name ) != harvestable_functions.end() ) { return iexamine_functions{&iexamine::harvestable_now, func}; } else { diff --git a/src/iexamine.h b/src/iexamine.h index 016b3bbc5ac80..ff1b061c19e48 100644 --- a/src/iexamine.h +++ b/src/iexamine.h @@ -46,6 +46,7 @@ void egg_sack_generic( Character &you, const tripoint &examp, const mtype_id &mo void none( Character &you, const tripoint &examp ); bool always_false( const tripoint &examp ); +bool false_and_debugmsg( const tripoint &examp ); bool always_true( const tripoint &examp ); bool harvestable_now( const tripoint &examp ); @@ -134,6 +135,7 @@ void workbench( Character &you, const tripoint &examp ); void workbench_internal( Character &you, const tripoint &examp, const cata::optional &part ); void workout( Character &you, const tripoint &examp ); +void invalid( Character &you, const tripoint &examp ); bool pour_into_keg( const tripoint &pos, item &liquid ); cata::optional getGasPumpByNumber( const tripoint &p, int number ); diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp index d8ca784f1a0bf..7294ad4fdce87 100644 --- a/src/inventory_ui.cpp +++ b/src/inventory_ui.cpp @@ -125,7 +125,7 @@ class selection_column_preset : public inventory_selector_preset nc_color get_color( const inventory_entry &entry ) const override { Character &player_character = get_player_character(); if( entry.is_item() ) { - if( &*entry.any_item() == player_character.get_wielded_item() ) { + if( &*entry.any_item() == &player_character.get_wielded_item() ) { return c_light_blue; } else if( player_character.is_worn( *entry.any_item() ) ) { return c_cyan; @@ -1478,7 +1478,7 @@ void inventory_selector::add_contained_ebooks( item_location &container ) void inventory_selector::add_character_items( Character &character, bool include_hidden ) { character.visit_items( [ this, &character, &include_hidden ]( item * it, item * ) { - if( it == character.get_wielded_item() ) { + if( it == &character.get_wielded_item() ) { add_item( own_gear_column, item_location( character, it ), &item_category_id( "WEAPON_HELD" ).obj(), include_hidden ); } else if( character.is_worn( *it ) ) { @@ -2284,7 +2284,7 @@ void inventory_selector::toggle_categorize_contained() if( ancestor.where() != item_location::type::character ) { // might have been merged from the map column custom_category = entry->get_category_ptr(); - } else if( &*ancestor == u.get_wielded_item() ) { + } else if( &*ancestor == &u.get_wielded_item() ) { custom_category = &item_category_id( "WEAPON_HELD" ).obj(); } else if( u.is_worn( *ancestor ) ) { custom_category = &item_category_id( "ITEMS_WORN" ).obj(); diff --git a/src/item.cpp b/src/item.cpp index deede77ad19a1..4acc608494ee1 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -10637,7 +10637,7 @@ bool item::process_extinguish( Character *carrier, const tripoint &pos ) extinguish = true; } if( !extinguish || - ( in_inv && precipitation && carrier->get_wielded_item()->has_flag( flag_RAIN_PROTECT ) ) ) { + ( in_inv && precipitation && carrier->get_wielded_item().has_flag( flag_RAIN_PROTECT ) ) ) { return false; //nothing happens } if( carrier != nullptr ) { @@ -10730,7 +10730,7 @@ bool item::process_cable( Character *carrier, const tripoint &pos ) } map &here = get_map(); - if( !here.veh_at( *source ) || ( source->z != here.get_abs_sub().z && !here.has_zlevels() ) ) { + if( !here.veh_at( *source ) ) { if( carrier->has_item( *this ) ) { carrier->add_msg_if_player( m_bad, _( "You notice the cable has come loose!" ) ); } diff --git a/src/iuse.cpp b/src/iuse.cpp index f2ad93555e0b8..d186dfe5f2f4b 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -61,6 +61,7 @@ #include "iuse_actor.h" // For firestarter #include "json.h" #include "line.h" +#include "make_static.h" #include "map.h" #include "map_iterator.h" #include "mapdata.h" @@ -4661,11 +4662,52 @@ cata::optional iuse::vortex( Character *p, item *it, bool, const tripoint & cata::optional iuse::dog_whistle( Character *p, item *it, bool, const tripoint & ) { + if( !p->is_avatar() ) { + return cata::nullopt; + } if( p->is_underwater() ) { p->add_msg_if_player( m_info, _( "You can't do that while underwater." ) ); return cata::nullopt; } p->add_msg_if_player( _( "You blow your dog whistle." ) ); + + std::array messages_friendly_or_neutral = { + _( "What is this unbearable sound!?" ), + _( "STOP. MY EARS" ), + _( "I'm not a dog…" ), + _( "Would you kindly not do that?" ) + }; + + std::array messages_hostile = { + _( "I WILL MURDER YOU" ), + _( "I'LL SHOVE THAT WHISTLE DOWN YOUR THROAT" ), + _( "You're seriously pissing me off…" ), + _( "I'm not a dog…" ), + _( "What is this unbearable sound!?" ), + }; + + // Can the Character hear the dog whistle? + auto hearing_check = [p]( const Character & who ) -> bool { + return !who.is_deaf() && p->sees( who ) && + who.has_trait( STATIC( trait_id( "THRESH_LUPINE" ) ) ); + }; + + for( const npc &subject : g->all_npcs() ) { + if( !( one_in( 3 ) && hearing_check( subject ) ) ) { + continue; + } + + if( p->attitude_to( subject ) == Creature::Attitude::HOSTILE ) { + subject.say( random_entry( messages_hostile ) ); + } else { + subject.say( random_entry( messages_friendly_or_neutral ) ); + } + } + + if( hearing_check( *p ) && one_in( 3 ) ) { + p->add_msg_if_player( m_info, _( "You hate this loud sound." ) ); + } + for( monster &critter : g->all_monsters() ) { if( critter.friendly != 0 && critter.has_flag( MF_DOGFOOD ) ) { bool u_see = get_player_view().sees( critter ); @@ -7665,7 +7707,7 @@ cata::optional iuse::ehandcuffs( Character *p, item *it, bool t, const trip it->unset_flag( flag_NO_UNWIELD ); it->active = false; - if( p->has_item( *it ) && p->get_wielded_item()->typeId() == itype_e_handcuffs ) { + if( p->has_item( *it ) && p->get_wielded_item().typeId() == itype_e_handcuffs ) { add_msg( m_good, _( "%s on your wrists opened!" ), it->tname() ); } @@ -7697,7 +7739,7 @@ cata::optional iuse::ehandcuffs( Character *p, item *it, bool t, const trip if( ( it->ammo_remaining() > it->type->maximum_charges() - 1000 ) && ( p2.x != pos.x || p2.y != pos.y ) ) { - if( p->has_item( *it ) && p->get_wielded_item()->typeId() == itype_e_handcuffs ) { + if( p->has_item( *it ) && p->get_wielded_item().typeId() == itype_e_handcuffs ) { if( p->is_elec_immune() ) { if( one_in( 10 ) ) { @@ -9347,10 +9389,6 @@ cata::optional iuse::capture_monster_act( Character *p, item *it, bool, con cata::optional iuse::ladder( Character *p, item *, bool, const tripoint & ) { map &here = get_map(); - if( !here.has_zlevels() ) { - debugmsg( "Ladder can't be used in non-z-level mode" ); - return cata::nullopt; - } if( p->is_mounted() ) { p->add_msg_if_player( m_info, _( "You can't do that while mounted." ) ); return cata::nullopt; @@ -9604,7 +9642,7 @@ static item *wield_before_use( Character *const p, item *const it, const std::st return nullptr; } // `it` is no longer the item we are using (note that `player::wielded` is a value). - return p->get_wielded_item(); + return &p->get_wielded_item(); } else { return nullptr; } diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 87309976235d1..77d64686672e2 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -1472,7 +1472,7 @@ bool salvage_actor::try_to_cut_up( Character &p, item &it ) const return false; } // Softer warnings at the end so we don't ask permission and then tell them no. - if( &it == p.get_wielded_item() ) { + if( &it == &p.get_wielded_item() ) { if( !query_yn( _( "You are wielding that, are you sure?" ) ) ) { return false; } diff --git a/src/lightmap.cpp b/src/lightmap.cpp index 64435183fe336..066dd720a0c3f 100644 --- a/src/lightmap.cpp +++ b/src/lightmap.cpp @@ -246,11 +246,10 @@ void map::apply_character_light( Character &p ) // Once this is complete, additional operations add more dynamic lighting. void map::build_sunlight_cache( int pzlev ) { - const int zlev_min = zlevels ? -OVERMAP_DEPTH : pzlev; + const int zlev_min = -OVERMAP_DEPTH; // Start at the topmost populated zlevel to avoid unnecessary raycasting // Plus one zlevel to prevent clipping inside structures - const int zlev_max = zlevels ? clamp( calc_max_populated_zlev() + 1, pzlev + 1, - OVERMAP_HEIGHT ) : pzlev; + const int zlev_max = clamp( calc_max_populated_zlev() + 1, pzlev + 1, OVERMAP_HEIGHT ); // true if all previous z-levels are fully transparent to light (no floors, transparency >= air) bool fully_outside = true; @@ -275,20 +274,6 @@ void map::build_sunlight_cache( int pzlev ) // TODO: if zlev < 0 is open to sunlight, this won't calculate correct light, but neither does g->natural_light_level() const float inside_light_level = ( zlev >= 0 && outside_light_level > LIGHT_SOURCE_BRIGHT ) ? LIGHT_AMBIENT_DIM * 0.8 : LIGHT_AMBIENT_LOW; - // Handling when z-levels are disabled is based on whether a tile is considered "outside". - if( !zlevels ) { - const auto &outside_cache = map_cache.outside_cache; - for( int x = 0; x < MAPSIZE_X; x++ ) { - for( int y = 0; y < MAPSIZE_Y; y++ ) { - if( outside_cache[x][y] ) { - lm[x][y].fill( outside_light_level ); - } else { - lm[x][y].fill( inside_light_level ); - } - } - } - continue; - } // all light was blocked before if( fully_inside ) { diff --git a/src/magic.cpp b/src/magic.cpp index 0a2422306ba9f..848406fa93c9f 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -889,7 +889,7 @@ bool spell::check_if_component_in_hand( Character &guy ) const const requirement_data &spell_components = type->spell_components.obj(); if( guy.has_weapon() ) { - if( spell_components.can_make_with_inventory( *guy.get_wielded_item(), return_true ) ) { + if( spell_components.can_make_with_inventory( guy.get_wielded_item(), return_true ) ) { return true; } } diff --git a/src/magic_teleporter_list.cpp b/src/magic_teleporter_list.cpp index 7a96144a176b9..b364d8fd313fe 100644 --- a/src/magic_teleporter_list.cpp +++ b/src/magic_teleporter_list.cpp @@ -77,7 +77,7 @@ static cata::optional find_valid_teleporters_omt( const tripoint_abs_o bool teleporter_list::place_avatar_overmap( Character &you, const tripoint_abs_omt &omt_pt ) const { - tinymap omt_dest( 2, true ); + tinymap omt_dest; tripoint_abs_sm sm_dest = project_to( omt_pt ); omt_dest.load( sm_dest, true ); cata::optional global_dest = find_valid_teleporters_omt( omt_pt ); diff --git a/src/map.cpp b/src/map.cpp index 344d8aa67c1e8..6eaa7e5d2f90b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -137,10 +137,9 @@ units::volume map_stack::max_volume() const // Map class methods. -map::map( int mapsize, bool zlev ) +map::map( int mapsize, bool zlev ) : my_MAPSIZE( mapsize ), zlevels( zlev ) { - my_MAPSIZE = mapsize; - zlevels = zlev; + if( zlevels ) { grid.resize( static_cast( my_MAPSIZE * my_MAPSIZE * OVERMAP_LAYERS ), nullptr ); } else { @@ -8169,11 +8168,6 @@ size_t map::get_nonant( const tripoint &gridp ) const } } -tinymap::tinymap( int mapsize, bool zlevels ) - : map( mapsize, zlevels ) -{ -} - void map::draw_line_ter( const ter_id &type, const point &p1, const point &p2 ) { draw_line( [this, type]( const point & p ) { diff --git a/src/map.h b/src/map.h index cee6ec56a1f27..b4a9e4eff142c 100644 --- a/src/map.h +++ b/src/map.h @@ -311,10 +311,11 @@ class map // for testing friend void clear_fields( int zlevel ); + protected: + map( int mapsize, bool zlev ); public: // Constructors & Initialization - explicit map( int mapsize = MAPSIZE, bool zlev = true ); - explicit map( bool zlev ) : map( MAPSIZE, zlev ) { } + map() : map( MAPSIZE, true ) { } virtual ~map(); map &operator=( const map & ) = delete; @@ -1667,9 +1668,6 @@ class map int getmapsize() const { return my_MAPSIZE; } - bool has_zlevels() const { - return zlevels; - } // Not protected/private for mapgen.cpp and mapgen_functions.cpp access // Rotates the current map 90*turns degrees clockwise @@ -2099,7 +2097,7 @@ class tinymap : public map { friend class editmap; public: - explicit tinymap( int mapsize = 2, bool zlevels = false ); + tinymap() : map( 2, false ) {} bool inbounds( const tripoint &p ) const override; /** Sometimes you need to generate and rotate a tinymap without touching npcs */ diff --git a/src/map_field.cpp b/src/map_field.cpp index aa1ef113a1bb8..6aeea9020a5bd 100644 --- a/src/map_field.cpp +++ b/src/map_field.cpp @@ -140,9 +140,7 @@ int map::burn_body_part( Character &you, field_entry &cur, const bodypart_id &bp void map::process_fields() { - const int minz = zlevels ? -OVERMAP_DEPTH : abs_sub.z; - const int maxz = zlevels ? OVERMAP_HEIGHT : abs_sub.z; - for( int z = minz; z <= maxz; z++ ) { + for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) { auto &field_cache = get_cache( z ).field_cache; for( int x = 0; x < my_MAPSIZE; x++ ) { for( int y = 0; y < my_MAPSIZE; y++ ) { @@ -287,7 +285,7 @@ void map::spread_gas( field_entry &cur, const tripoint &p, int percent_spread, // First check if we can fall // TODO: Make fall and rise chances parameters to enable heavy/light gas - if( zlevels && p.z > -OVERMAP_DEPTH ) { + if( p.z > -OVERMAP_DEPTH ) { const tripoint down{ p.xy(), p.z - 1 }; maptile down_tile = maptile_at_internal( down ); if( gas_can_spread_to( cur, down_tile ) && valid_move( p, down, true, true ) ) { @@ -312,7 +310,7 @@ void map::spread_gas( field_entry &cur, const tripoint &p, int percent_spread, } } - if( !spread.empty() && ( !zlevels || one_in( spread.size() ) ) ) { + if( !spread.empty() && one_in( spread.size() ) ) { // Construct the destination from offset and p if( sheltered || windpower < 5 ) { std::pair &n = neighs[ random_entry( spread ) ]; @@ -338,7 +336,7 @@ void map::spread_gas( field_entry &cur, const tripoint &p, int percent_spread, gas_spread_to( cur, n.second, n.first ); } } - } else if( zlevels && p.z < OVERMAP_HEIGHT ) { + } else if( p.z < OVERMAP_HEIGHT ) { const tripoint up{ p.xy(), p.z + 1 }; maptile up_tile = maptile_at_internal( up ); if( gas_can_spread_to( cur, up_tile ) && valid_move( p, up, true, true ) ) { @@ -502,7 +500,7 @@ static void field_processor_underwater_dissipation( const tripoint &, field_entr static void field_processor_fd_acid( const tripoint &p, field_entry &cur, field_proc_data &pd ) { //cur_fd_type_id == fd_acid - if( !pd.here.has_zlevels() || p.z <= -OVERMAP_DEPTH ) { + if( p.z <= -OVERMAP_DEPTH ) { return; } @@ -1053,8 +1051,7 @@ void field_processor_fd_fire( const tripoint &p, field_entry &cur, field_proc_da here.add_item_or_charges( p, item( "ash" ) ); } - } else if( ter.has_flag( ter_furn_flag::TFLAG_NO_FLOOR ) && here.has_zlevels() && - p.z > -OVERMAP_DEPTH ) { + } else if( ter.has_flag( ter_furn_flag::TFLAG_NO_FLOOR ) && p.z > -OVERMAP_DEPTH ) { // We're hanging in the air - let's fall down tripoint dst{ p.xy(), p.z - 1 }; if( here.valid_move( p, dst, true, true ) ) { @@ -1222,7 +1219,7 @@ void field_processor_fd_fire( const tripoint &p, field_entry &cur, field_proc_da // Consume adjacent fuel / terrain / webs to spread. // Allow raging fires (and only raging fires) to spread up // Spreading down is achieved by wrecking the walls/floor and then falling - if( here.has_zlevels() && cur.get_field_intensity() == 3 && p.z < OVERMAP_HEIGHT ) { + if( cur.get_field_intensity() == 3 && p.z < OVERMAP_HEIGHT ) { const tripoint dst_p = tripoint( p.xy(), p.z + 1 ); // Let it burn through the floor maptile dst = here.maptile_at_internal( dst_p ); @@ -1363,7 +1360,7 @@ void field_processor_fd_fire( const tripoint &p, field_entry &cur, field_proc_da if( !ter_furn_has_flag( ter, frn, ter_furn_flag::TFLAG_SUPPRESS_SMOKE ) && rng( 0, 100 - windpower ) <= smoke && rng( 3, 35 ) < cur.get_field_intensity() * 10 ) { - bool smoke_up = here.has_zlevels() && p.z < OVERMAP_HEIGHT; + bool smoke_up = p.z < OVERMAP_HEIGHT; if( smoke_up ) { tripoint up{p.xy(), p.z + 1}; if( here.has_flag_ter( ter_furn_flag::TFLAG_NO_FLOOR, up ) ) { diff --git a/src/map_selector.cpp b/src/map_selector.cpp index c29af4826805e..d49adc22b28c2 100644 --- a/src/map_selector.cpp +++ b/src/map_selector.cpp @@ -26,11 +26,9 @@ map_selector::map_selector( const tripoint &pos, int radius, bool accessible ) tripoint_range points_in_range( const map &m ) { - const int z = m.get_abs_sub().z; - const bool hasz = m.has_zlevels(); return tripoint_range( - tripoint( 0, 0, hasz ? -OVERMAP_DEPTH : z ), - tripoint( SEEX * m.getmapsize() - 1, SEEY * m.getmapsize() - 1, hasz ? OVERMAP_HEIGHT : z ) ); + tripoint( 0, 0, -OVERMAP_DEPTH ), + tripoint( SEEX * m.getmapsize() - 1, SEEY * m.getmapsize() - 1, OVERMAP_HEIGHT ) ); } cata::optional random_point( const map &m, diff --git a/src/mapbuffer.cpp b/src/mapbuffer.cpp index 4c8249a0c7b2d..fb2d94ada8f0f 100644 --- a/src/mapbuffer.cpp +++ b/src/mapbuffer.cpp @@ -114,7 +114,7 @@ void mapbuffer::save( bool delete_after_save ) map &here = get_map(); const tripoint map_origin = sm_to_omt_copy( here.get_abs_sub() ); - const bool map_has_zlevels = g != nullptr && here.has_zlevels(); + const bool map_has_zlevels = g != nullptr; static_popup popup; diff --git a/src/mapdata.cpp b/src/mapdata.cpp index 41528a16b66a1..c666169ecabb4 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -497,7 +497,7 @@ std::string map_data_common_t::name() const bool map_data_common_t::can_examine( const tripoint &examp ) const { - return examine_func.can_examine( examp ); + return examine_actor || examine_func.can_examine( examp ); } bool map_data_common_t::has_examine( iexamine_examine_function func ) const @@ -1301,6 +1301,7 @@ void map_data_common_t::load( const JsonObject &jo, const std::string & ) JsonObject data = jo.get_object( "examine_action" ); examine_actor = iexamine_actor_from_jsobj( data ); examine_actor->load( data ); + examine_func = iexamine_functions_from_string( "invalid" ); } else { examine_func = iexamine_functions_from_string( "none" ); } diff --git a/src/mapdata.h b/src/mapdata.h index 86b15c5f32cea..3d6ced504c9f0 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -31,9 +31,6 @@ struct furn_t; struct itype; struct tripoint; -using iexamine_function = void ( * )( Character &, const tripoint & ); -using iexamine_function_ref = void( & )( Character &, const tripoint & ); - template struct enum_traits; struct map_bash_info { diff --git a/src/martialarts.cpp b/src/martialarts.cpp index d777194c7f512..f55e721930d39 100644 --- a/src/martialarts.cpp +++ b/src/martialarts.cpp @@ -1501,7 +1501,7 @@ bool ma_style_callback::key( const input_context &ctxt, const input_event &event std::back_inserter( weapons ), []( const itype_id & wid )-> std::string { // Colorize wielded weapon and move it to the front of the list Character &player_character = get_player_character(); - if( item::nname( wid ) == player_character.get_wielded_item()->display_name() ) + if( item::nname( wid ) == player_character.get_wielded_item().display_name() ) { return colorize( item::nname( wid ) + _( " (wielded)" ), c_light_cyan ); } else diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index a48c95fe370d8..593101c5733ec 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -622,7 +622,7 @@ void gun_actor::shoot( monster &z, Creature &target, const gun_mode_id &mode ) c 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() ); + tmp.get_wielded_item().tname() ); if( throwing ) { tmp.throw_item( target.pos(), item( ammo, calendar::turn, 1 ) ); diff --git a/src/melee.cpp b/src/melee.cpp index 378f8db301b2f..31cde46e8c527 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -2572,13 +2572,13 @@ void avatar::disarm( npc &target ) their_roll += dice( 3, target.get_per() ); their_roll += dice( 3, target.get_skill_level( skill_melee ) ); - item &it = *target.get_wielded_item(); - const item *weapon = get_wielded_item(); + item &it = target.get_wielded_item(); + const item &weapon = get_wielded_item(); // roll your melee and target's dodge skills to check if grab/smash attack succeeds int hitspread = target.deal_melee_attack( this, hit_roll() ); if( hitspread < 0 ) { add_msg( _( "You lunge for the %s, but miss!" ), it.tname() ); - mod_moves( -100 - stumble( *this, *weapon ) - attack_speed( *weapon ) ); + mod_moves( -100 - stumble( *this, weapon ) - attack_speed( weapon ) ); target.on_attacked( *this ); return; } @@ -2613,7 +2613,7 @@ void avatar::disarm( npc &target ) } // Make their weapon fall on floor if we've rolled enough. - mod_moves( -100 - attack_speed( *get_wielded_item() ) ); + mod_moves( -100 - attack_speed( get_wielded_item() ) ); if( my_roll >= their_roll ) { add_msg( _( "You smash %s with all your might forcing their %s to drop down nearby!" ), target.get_name(), it.tname() ); diff --git a/src/memorial_logger.cpp b/src/memorial_logger.cpp index 7a602de7fb4da..9b41733e4e3a9 100644 --- a/src/memorial_logger.cpp +++ b/src/memorial_logger.cpp @@ -352,9 +352,9 @@ void memorial_logger::write_text_memorial( std::ostream &file, file << eol; //Equipment - const item *weapon = u.get_wielded_item(); + const item &weapon = u.get_wielded_item(); file << _( "Weapon:" ) << eol; - file << indent << weapon->invlet << " - " << weapon->tname( 1, false ) << eol; + file << indent << weapon.invlet << " - " << weapon.tname( 1, false ) << eol; file << eol; file << _( "Equipment:" ) << eol; diff --git a/src/monattack.cpp b/src/monattack.cpp index 8431524f60541..911a5d9a2a489 100644 --- a/src/monattack.cpp +++ b/src/monattack.cpp @@ -796,12 +796,12 @@ bool mattack::pull_metal_weapon( monster *z ) Character *foe = dynamic_cast< Character * >( target ); if( foe != nullptr ) { // Wielded steel or iron items except for built-in things like bionic claws or monomolecular blade - const item *weapon = foe->get_wielded_item(); - if( !weapon->has_flag( flag_NO_UNWIELD ) && - ( weapon->made_of( material_id( "iron" ) ) || - weapon->made_of( material_id( "hardsteel" ) ) || - weapon->made_of( material_id( "steel" ) ) || - weapon->made_of( material_id( "budget_steel" ) ) ) ) { + const item &weapon = foe->get_wielded_item(); + if( !weapon.has_flag( flag_NO_UNWIELD ) && + ( weapon.made_of( material_id( "iron" ) ) || + weapon.made_of( material_id( "hardsteel" ) ) || + weapon.made_of( material_id( "steel" ) ) || + weapon.made_of( material_id( "budget_steel" ) ) ) ) { const int wp_skill = foe->get_skill_level( skill_melee ); // It takes a while z->moves -= att_cost_pull; @@ -2721,7 +2721,7 @@ bool mattack::grab( monster *z ) target->add_msg_if_player( m_info, _( "The %s tries to grab you as well, but you bat it away!" ), z->name() ); } else if( pl->is_throw_immune() && ( !pl->is_armed() || - pl->martial_arts_data->selected_has_weapon( pl->get_wielded_item()->typeId() ) ) ) { + pl->martial_arts_data->selected_has_weapon( pl->get_wielded_item().typeId() ) ) ) { target->add_msg_if_player( m_info, _( "The %s tries to grab you…" ), z->name() ); thrown_by_judo( z ); } else { @@ -3247,7 +3247,7 @@ bool mattack::photograph( monster *z ) } } - if( z->friendly || player_character.get_wielded_item()->typeId() == itype_e_handcuffs ) { + if( z->friendly || player_character.get_wielded_item().typeId() == itype_e_handcuffs ) { // Friendly (hacked?) bot ignore the player. Arrested suspect ignored too. // TODO: might need to be revisited when it can target npcs. return false; @@ -3265,7 +3265,7 @@ bool mattack::photograph( monster *z ) string_format( _( "a robotic voice boom, \"Citizen %s!\"" ), cname ), false, "speech", z->type->id.str() ); - if( player_character.get_wielded_item()->is_gun() ) { + if( player_character.get_wielded_item().is_gun() ) { sounds::sound( z->pos(), 15, sounds::sound_t::alert, _( "\"Drop your gun! Now!\"" ) ); } else if( player_character.is_armed() ) { sounds::sound( z->pos(), 15, sounds::sound_t::alert, _( "\"Drop your weapon! Now!\"" ) ); @@ -3357,10 +3357,10 @@ void mattack::rifle( monster *z, Creature *target ) tmp.set_wielded_item( item( "m4_carbine" ).ammo_set( ammo_type, z->ammo[ ammo_type ] ) ); - item *weapon = tmp.get_wielded_item(); - int burst = std::max( weapon->gun_get_mode( gun_mode_id( "AUTO" ) ).qty, 1 ); + item &weapon = tmp.get_wielded_item(); + int burst = std::max( weapon.gun_get_mode( gun_mode_id( "AUTO" ) ).qty, 1 ); - z->ammo[ ammo_type ] -= tmp.fire_gun( target->pos(), burst ) * weapon->ammo_required(); + z->ammo[ ammo_type ] -= tmp.fire_gun( target->pos(), burst ) * weapon.ammo_required(); if( target && target->is_avatar() ) { z->add_effect( effect_targeted, 3_turns ); @@ -3417,10 +3417,10 @@ void mattack::frag( monster *z, Creature *target ) // This is for the bots, not add_msg_if_player_sees( *z, m_warning, _( "The %s's grenade launcher fires!" ), z->name() ); tmp.set_wielded_item( item( "mgl" ).ammo_set( ammo_type, z->ammo[ ammo_type ] ) ); - const item *weapon = tmp.get_wielded_item(); - int burst = std::max( weapon->gun_get_mode( gun_mode_id( "AUTO" ) ).qty, 1 ); + const item &weapon = tmp.get_wielded_item(); + int burst = std::max( weapon.gun_get_mode( gun_mode_id( "AUTO" ) ).qty, 1 ); - z->ammo[ ammo_type ] -= tmp.fire_gun( target->pos(), burst ) * weapon->ammo_required(); + z->ammo[ ammo_type ] -= tmp.fire_gun( target->pos(), burst ) * weapon.ammo_required(); if( target && target->is_avatar() ) { z->add_effect( effect_targeted, 3_turns ); @@ -3475,10 +3475,10 @@ void mattack::tankgun( monster *z, Creature *target ) } add_msg_if_player_sees( *z, m_warning, _( "The %s's 120mm cannon fires!" ), z->name() ); tmp.set_wielded_item( item( "TANK" ).ammo_set( ammo_type, z->ammo[ ammo_type ] ) ); - const item *weapon = tmp.get_wielded_item(); - int burst = std::max( weapon->gun_get_mode( gun_mode_id( "AUTO" ) ).qty, 1 ); + const item &weapon = tmp.get_wielded_item(); + int burst = std::max( weapon.gun_get_mode( gun_mode_id( "AUTO" ) ).qty, 1 ); - z->ammo[ ammo_type ] -= tmp.fire_gun( target->pos(), burst ) * weapon->ammo_required(); + z->ammo[ ammo_type ] -= tmp.fire_gun( target->pos(), burst ) * weapon.ammo_required(); } bool mattack::searchlight( monster *z ) @@ -3765,7 +3765,7 @@ bool mattack::copbot( monster *z ) // TODO: Make it recognize zeds as human, but ignore animals Character *foe = dynamic_cast( target ); bool sees_u = foe != nullptr && z->sees( *foe ); - bool cuffed = foe != nullptr && foe->get_wielded_item()->typeId() == itype_e_handcuffs; + bool cuffed = foe != nullptr && foe->get_wielded_item().typeId() == itype_e_handcuffs; // Taze first, then ask questions (simplifies later checks for non-humans) if( !cuffed && z->is_adjacent( target, true ) ) { taze( z, target ); @@ -4719,7 +4719,7 @@ bool mattack::riotbot( monster *z ) //already arrested? //and yes, if the player has no hands, we are not going to arrest him. if( foe != nullptr && - ( foe->get_wielded_item()->typeId() == itype_e_handcuffs || !foe->has_two_arms_lifting() ) ) { + ( foe->get_wielded_item().typeId() == itype_e_handcuffs || !foe->has_two_arms_lifting() ) ) { z->anger = 0; if( calendar::once_every( 25_turns ) ) { @@ -5232,7 +5232,7 @@ bool mattack::bio_op_takedown( monster *z ) foe->add_effect( effect_downed, 3_turns ); } } else if( ( !foe->is_armed() || - foe->martial_arts_data->selected_has_weapon( foe->get_wielded_item()->typeId() ) ) && + foe->martial_arts_data->selected_has_weapon( foe->get_wielded_item().typeId() ) ) && !thrown_by_judo( z ) ) { // Saved by the tentacle-bracing! :) hit = bodypart_id( "torso" ); @@ -5370,7 +5370,7 @@ bool mattack::bio_op_disarm( monster *z ) their_roll += dice( 3, foe->get_per() ); their_roll += dice( 3, foe->get_skill_level( skill_melee ) ); - item &it = *foe->get_wielded_item(); + item &it = foe->get_wielded_item(); target->add_msg_if_player( m_bad, _( "The zombie grabs your %s…" ), it.tname() ); @@ -5882,9 +5882,9 @@ bool mattack::dsa_drone_scan( monster *z ) } target->set_value( timestamp_str, string_format( "%d", to_turn( calendar::turn ) ) ); if( weapons_count < 3 ) { - const item *weapon = target->get_wielded_item(); - if( weapon->is_gun() ) { - const gun_type_type &guntype = weapon->gun_type(); + const item &weapon = target->get_wielded_item(); + if( weapon.is_gun() ) { + const gun_type_type &guntype = weapon.gun_type(); if( guntype == gun_type_type( "rifle" ) || guntype == gun_type_type( "shotgun" ) || guntype == gun_type_type( "launcher" ) ) { diff --git a/src/mondefense.cpp b/src/mondefense.cpp index ed38db86c33be..e0edff9dee962 100644 --- a/src/mondefense.cpp +++ b/src/mondefense.cpp @@ -200,11 +200,11 @@ void mdefense::return_fire( monster &m, Creature *source, const dealt_projectile // ...and weapon, everything based on turret's properties tmp.set_wielded_item( item( gunactor->gun_type ).ammo_set( gunactor->ammo_type, m.ammo[ gunactor->ammo_type ] ) ); - const item *weapon = tmp.get_wielded_item(); - const int burst = std::max( weapon->gun_get_mode( gun_mode_id( "DEFAULT" ) ).qty, 1 ); + const item &weapon = tmp.get_wielded_item(); + const int burst = std::max( weapon.gun_get_mode( gun_mode_id( "DEFAULT" ) ).qty, 1 ); // Fire the weapon and consume ammo - m.ammo[ gunactor->ammo_type ] -= tmp.fire_gun( fire_point, burst ) * weapon->ammo_required(); + m.ammo[ gunactor->ammo_type ] -= tmp.fire_gun( fire_point, burst ) * weapon.ammo_required(); } } } diff --git a/src/monexamine.cpp b/src/monexamine.cpp index 41d2c90a7f5a0..7abee6ab218be 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -690,9 +690,9 @@ bool monexamine::pet_menu( monster &z ) } amenu.addentry( check_bat, false, 'c', _( "%s battery level is %d%%" ), z.get_name(), static_cast( charge_percent ) ); - if( player_character.get_wielded_item()->is_null() && z.battery_item ) { + if( player_character.get_wielded_item().is_null() && z.battery_item ) { amenu.addentry( mount, true, 'r', _( "Climb into the mech and take control" ) ); - } else if( !player_character.get_wielded_item()->is_null() ) { + } else if( !player_character.get_wielded_item().is_null() ) { amenu.addentry( mount, false, 'r', _( "You cannot pilot the mech whilst wielding something" ) ); } else if( !z.battery_item ) { amenu.addentry( mount, false, 'r', _( "This mech has a dead battery and won't turn on" ) ); diff --git a/src/monmove.cpp b/src/monmove.cpp index 43bb1b2c765e1..4ff5bb67d21aa 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -918,11 +918,6 @@ void monster::move() } } - if( !here.has_zlevels() ) { - // Otherwise weird things happen - destination.z = posz(); - } - point new_d( destination.xy() - pos().xy() ); // toggle facing direction for sdl flip @@ -1961,13 +1956,11 @@ void monster::stumble() } } } - - if( here.has_zlevels() ) { - tripoint below( posx(), posy(), posz() - 1 ); - if( here.valid_move( pos(), below, false, true ) ) { - valid_stumbles.push_back( below ); - } + const tripoint below( posx(), posy(), posz() - 1 ); + if( here.valid_move( pos(), below, false, true ) ) { + valid_stumbles.push_back( below ); } + creature_tracker &creatures = get_creature_tracker(); while( !valid_stumbles.empty() && !is_dead() ) { const tripoint dest = random_entry_removed( valid_stumbles ); diff --git a/src/npc.cpp b/src/npc.cpp index 8ea403759e1b8..9af53bde832e6 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -659,16 +659,16 @@ void starting_inv( npc &who, const npc_class_id &type ) } res.emplace_back( lighter ); // If wielding a gun, get some additional ammo for it - const item *weapon = who.get_wielded_item(); - if( weapon->is_gun() ) { + const item &weapon = who.get_wielded_item(); + if( weapon.is_gun() ) { item ammo; - if( !weapon->magazine_default().is_null() ) { - item mag( weapon->magazine_default() ); + if( !weapon.magazine_default().is_null() ) { + item mag( weapon.magazine_default() ); mag.ammo_set( mag.ammo_default() ); ammo = item( mag.ammo_default() ); res.push_back( mag ); - } else if( !weapon->ammo_default().is_null() ) { - ammo = item( weapon->ammo_default() ); + } else if( !weapon.ammo_default().is_null() ) { + ammo = item( weapon.ammo_default() ); // TODO: Move to npc_class // NC_COWBOY and NC_BOUNTY_HUNTER get 5-15 whilst all others get 3-6 int qty = 1 + ( type == NC_COWBOY || @@ -874,35 +874,35 @@ void npc::starting_weapon( const npc_class_id &type ) } else if( best == skill_rifle ) { set_wielded_item( random_item_from( type, "rifle", item_group_id( "guns_rifle_common" ) ) ); } - item *weapon = get_wielded_item(); - if( weapon->is_gun() ) { - if( !weapon->magazine_default().is_null() ) { - weapon->ammo_set( weapon->magazine_default()->magazine->default_ammo ); - } else if( !weapon->ammo_default().is_null() ) { - weapon->ammo_set( weapon->ammo_default() ); + item &weapon = get_wielded_item(); + if( weapon.is_gun() ) { + if( !weapon.magazine_default().is_null() ) { + weapon.ammo_set( weapon.magazine_default()->magazine->default_ammo ); + } else if( !weapon.ammo_default().is_null() ) { + weapon.ammo_set( weapon.ammo_default() ); } else { - debugmsg( "tried setting ammo for %s which has no magazine or ammo", weapon->typeId().c_str() ); + debugmsg( "tried setting ammo for %s which has no magazine or ammo", weapon.typeId().c_str() ); } //You should be able to wield your starting weapon - if( !meets_stat_requirements( *weapon ) ) { - if( weapon->get_min_str() > get_str() ) { - str_max = weapon->get_min_str(); + if( !meets_stat_requirements( weapon ) ) { + if( weapon.get_min_str() > get_str() ) { + str_max = weapon.get_min_str(); } - if( weapon->type->min_dex > get_dex() ) { - dex_max = weapon->type->min_dex; + if( weapon.type->min_dex > get_dex() ) { + dex_max = weapon.type->min_dex; } - if( weapon->type->min_int > get_int() ) { - int_max = weapon->type->min_int; + if( weapon.type->min_int > get_int() ) { + int_max = weapon.type->min_int; } - if( weapon->type->min_per > get_per() ) { - per_max = weapon->type->min_per; + if( weapon.type->min_per > get_per() ) { + per_max = weapon.type->min_per; } } } - get_event_bus().send( getID(), weapon->typeId() ); + get_event_bus().send( getID(), weapon.typeId() ); - weapon->set_owner( get_faction()->id ); + weapon.set_owner( get_faction()->id ); } bool npc::can_read( const item &book, std::vector &fail_reasons ) @@ -1115,28 +1115,28 @@ bool npc::wield( item &it ) invalidate_inventory_validity_cache(); cached_info.erase( "weapon_value" ); - item *weapon = get_wielded_item(); + item &weapon = get_wielded_item(); if( has_wield_conflicts( to_wield ) ) { - stow_item( *weapon ); + stow_item( weapon ); } if( to_wield.is_null() ) { set_wielded_item( item() ); - get_event_bus().send( getID(), weapon->typeId() ); + get_event_bus().send( getID(), weapon.typeId() ); return true; } moves -= 15; - if( to_wield.can_combine( *weapon ) ) { - weapon->combine( to_wield ); + if( to_wield.can_combine( weapon ) ) { + weapon.combine( to_wield ); } else { set_wielded_item( to_wield ); } - get_event_bus().send( getID(), weapon->typeId() ); + get_event_bus().send( getID(), weapon.typeId() ); if( get_player_view().sees( pos() ) ) { - add_msg_if_npc( m_info, _( " wields a %s." ), weapon->tname() ); + add_msg_if_npc( m_info, _( " wields a %s." ), weapon.tname() ); } invalidate_range_cache(); return true; @@ -1153,11 +1153,11 @@ void npc::drop( const drop_locations &what, const tripoint &target, void npc::invalidate_range_cache() { - const item *weapon = get_wielded_item(); - if( weapon->is_gun() ) { - confident_range_cache = confident_shoot_range( *weapon, get_most_accurate_sight( *weapon ) ); + const item &weapon = get_wielded_item(); + if( weapon.is_gun() ) { + confident_range_cache = confident_shoot_range( weapon, get_most_accurate_sight( weapon ) ); } else { - confident_range_cache = weapon->reach_range( *this ); + confident_range_cache = weapon.reach_range( *this ); } } @@ -1471,18 +1471,18 @@ std::vector npc::spells_offered_to( Character &you ) void npc::decide_needs() { - const item *weapon = get_wielded_item(); + const item &weapon = get_wielded_item(); double needrank[num_needs]; for( auto &elem : needrank ) { elem = 20; } - if( weapon->is_gun() ) { - int ups_drain = weapon->get_gun_ups_drain(); + if( weapon.is_gun() ) { + int ups_drain = weapon.get_gun_ups_drain(); if( ups_drain > 0 ) { int ups_charges = available_ups(); needrank[need_ammo] = static_cast( ups_charges ) / ups_drain; } else { - const ammotype ammo_type = weapon->ammo_type(); + const ammotype ammo_type = weapon.ammo_type(); if( ammo_type != ammotype::NULL_ID() ) { needrank[need_ammo] = get_ammo( ammo_type ).size(); } @@ -1493,7 +1493,7 @@ void npc::decide_needs() needrank[need_safety] = 1; } - needrank[need_weapon] = weapon_value( *weapon ); + needrank[need_weapon] = weapon_value( weapon ); needrank[need_food] = 15 - get_hunger(); needrank[need_drink] = 15 - get_thirst(); const auto inv_food = items_with( []( const item & itm ) { @@ -2177,7 +2177,7 @@ void npc::npc_dismount() remove_effect( effect_riding ); if( mounted_creature->has_flag( MF_RIDEABLE_MECH ) && !mounted_creature->type->mech_weapon.is_empty() ) { - remove_item( *get_wielded_item() ); + remove_item( get_wielded_item() ); } mounted_creature->remove_effect( effect_ridden ); mounted_creature->add_effect( effect_controlled, 5_turns ); @@ -2204,7 +2204,7 @@ float npc::danger_assessment() float npc::average_damage_dealt() { - return static_cast( melee_value( *get_wielded_item() ) ); + return static_cast( melee_value( get_wielded_item() ) ); } bool npc::bravery_check( int diff ) diff --git a/src/npc_attack.cpp b/src/npc_attack.cpp index 970e8f53d7566..78841635e6c52 100644 --- a/src/npc_attack.cpp +++ b/src/npc_attack.cpp @@ -93,7 +93,7 @@ npc_attack_rating npc_attack_rating::operator-=( const int rhs ) void npc_attack_spell::use( npc &source, const tripoint &location ) const { spell &sp = source.magic->get_spell( attack_spell_id ); - if( source.has_weapon() && !source.get_wielded_item()->has_flag( flag_id( "MAGIC_FOCUS" ) ) && + if( source.has_weapon() && !source.get_wielded_item().has_flag( flag_id( "MAGIC_FOCUS" ) ) && !sp.has_flag( spell_flag::NO_HANDS ) ) { source.unwield(); } @@ -563,8 +563,8 @@ std::vector npc_attack_activate_item::all_evaluations( const void npc_attack_throw::use( npc &source, const tripoint &location ) const { - if( !source.is_wielding( *source.get_wielded_item() ) ) { - if( !source.wield( *source.get_wielded_item() ) ) { + if( !source.is_wielding( source.get_wielded_item() ) ) { + if( !source.wield( source.get_wielded_item() ) ) { debugmsg( "ERROR: npc tried to equip a weapon it couldn't wield" ); } return; @@ -582,10 +582,10 @@ void npc_attack_throw::use( npc &source, const tripoint &location ) const } add_msg_debug( debugmode::debug_filter::DF_NPC, "%s throws the %s", source.disp_name(), - source.get_wielded_item()->display_name() ); - item thrown( *source.get_wielded_item() ); - if( source.get_wielded_item()->count_by_charges() && source.get_wielded_item()->charges > 1 ) { - source.get_wielded_item()->mod_charges( -1 ); + source.get_wielded_item().display_name() ); + item thrown( source.get_wielded_item() ); + if( source.get_wielded_item().count_by_charges() && source.get_wielded_item().charges > 1 ) { + source.get_wielded_item().mod_charges( -1 ); thrown.charges = 1; } else { source.remove_weapon(); diff --git a/src/npcmove.cpp b/src/npcmove.cpp index d56905fd70fda..55bfcf67d7a81 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -210,7 +210,7 @@ bool good_for_pickup( const item &it, npc &who ) ( ( !whitelisting && who.value( it ) > min_value ) || who.item_whitelisted( it ) ) && ( it.weight() <= weight_allowed ) && ( who.can_stash( it ) || - who.weapon_value( it ) > who.weapon_value( *who.get_wielded_item() ) ) ) { + who.weapon_value( it ) > who.weapon_value( who.get_wielded_item() ) ) ) { good = true; } @@ -745,7 +745,7 @@ void npc::regen_ai_cache() ai_cache.can_heal.clear_all(); ai_cache.danger = 0.0f; ai_cache.total_danger = 0.0f; - ai_cache.my_weapon_value = weapon_value( *get_wielded_item() ); + ai_cache.my_weapon_value = weapon_value( get_wielded_item() ); ai_cache.dangerous_explosives = find_dangerous_explosives(); assess_danger(); @@ -795,13 +795,13 @@ void npc::move() npc_action action = npc_undecided; - const item *weapon = get_wielded_item(); + const item &weapon = get_wielded_item(); static const std::string no_target_str = "none"; const Creature *target = current_target(); const std::string &target_name = target != nullptr ? target->disp_name() : no_target_str; add_msg_debug( debugmode::DF_NPC, "NPC %s: target = %s, danger = %.1f, range = %d", - get_name(), target_name, ai_cache.danger, weapon->is_gun() ? confident_shoot_range( *weapon, - recoil_total() ) : weapon->reach_range( *this ) ); + get_name(), target_name, ai_cache.danger, weapon.is_gun() ? confident_shoot_range( weapon, + recoil_total() ) : weapon.reach_range( *this ) ); Character &player_character = get_player_character(); //faction opinion determines if it should consider you hostile @@ -1054,7 +1054,7 @@ void npc::execute_action( npc_action action ) worker_downtime(); break; case npc_reload: { - do_reload( *get_wielded_item() ); + do_reload( get_wielded_item() ); } break; @@ -1175,7 +1175,7 @@ void npc::execute_action( npc_action action ) break; case npc_shoot: { - gun_mode mode = get_wielded_item()->gun_current_mode(); + gun_mode mode = get_wielded_item().gun_current_mode(); if( !mode ) { debugmsg( "NPC tried to shoot without valid mode" ); break; @@ -1542,12 +1542,12 @@ const item &npc::find_reloadable() const bool npc::can_reload_current() { - const item *weapon = get_wielded_item(); - if( !weapon->is_gun() || !wants_to_reload( *this, *weapon ) ) { + const item &weapon = get_wielded_item(); + if( !weapon.is_gun() || !wants_to_reload( *this, weapon ) ) { return false; } - return static_cast( find_usable_ammo( *weapon ) ); + return static_cast( find_usable_ammo( weapon ) ); } item_location npc::find_usable_ammo( const item &weap ) @@ -2140,13 +2140,13 @@ bool npc::enough_time_to_reload( const item &gun ) const void npc::aim() { - const item *weapon = get_wielded_item(); - double aim_amount = aim_per_move( *weapon, recoil ); + const item &weapon = get_wielded_item(); + double aim_amount = aim_per_move( weapon, recoil ); while( aim_amount > 0 && recoil > 0 && moves > 0 ) { moves--; recoil -= aim_amount; recoil = std::max( 0.0, recoil ); - aim_amount = aim_per_move( *weapon, recoil ); + aim_amount = aim_per_move( weapon, recoil ); } } @@ -2378,7 +2378,7 @@ void npc::move_to( const tripoint &pt, bool no_bashing, std::set *nomo } } else if( !no_bashing && smash_ability() > 0 && here.is_bashable( p ) && here.bash_rating( smash_ability(), p ) > 0 ) { - moves -= !is_armed() ? 80 : get_wielded_item()->attack_time() * 0.8; + moves -= !is_armed() ? 80 : get_wielded_item().attack_time() * 0.8; here.bash( p, smash_ability() ); } else { if( attitude == NPCATT_MUG || @@ -2666,7 +2666,7 @@ void npc::move_pause() } // NPCs currently always aim when using a gun, even with no target // This simulates them aiming at stuff just at the edge of their range - if( !get_wielded_item()->is_gun() ) { + if( !get_wielded_item().is_gun() ) { pause(); return; } @@ -3348,10 +3348,10 @@ bool npc::wield_better_weapon() bool can_use_gun = ( !is_player_ally() || rules.has_flag( ally_rule::use_guns ) ); bool use_silent = ( is_player_ally() && rules.has_flag( ally_rule::use_silent ) ); - item *weapon = get_wielded_item(); + item &weapon = get_wielded_item(); // Check if there's something better to wield - item *best = weapon; + item *best = &weapon; double best_value = -100.0; const int ups_charges = available_ups(); @@ -3378,7 +3378,7 @@ bool npc::wield_better_weapon() } }; - compare_weapon( *weapon ); + compare_weapon( weapon ); // To prevent changing to barely better stuff best_value *= std::max( 1.0f, ai_cache.danger_assessment / 10.0f ); @@ -3401,7 +3401,7 @@ bool npc::wield_better_weapon() // Needs to check reload speed, RELOAD_ONE etc. // Until then, the NPCs should reload the guns as a last resort - if( best == weapon ) { + if( best == &weapon ) { add_msg_debug( debugmode::DF_NPC, "Wielded %s is best at %.1f, not switching", best->type->get_id().str(), best_value ); @@ -3496,7 +3496,7 @@ bool npc::alt_attack() used_dangerous = used_dangerous || dangerous; }; - check_alt_item( *get_wielded_item() ); + check_alt_item( get_wielded_item() ); const auto inv_all = items_with( []( const item & ) { return true; } ); @@ -4126,13 +4126,6 @@ void npc::set_omt_destination() return; } - // all of the following luxuries are at ground level. - // so please wallow in hunger & fear if below ground. - if( posz() != 0 && !get_map().has_zlevels() ) { - goal = no_goal_point; - return; - } - tripoint_abs_omt surface_omt_loc = global_omt_location(); // We need that, otherwise find_closest won't work properly surface_omt_loc.z() = 0; diff --git a/src/npctrade.cpp b/src/npctrade.cpp index 3678e815e67e1..88a397a3909d5 100644 --- a/src/npctrade.cpp +++ b/src/npctrade.cpp @@ -116,13 +116,13 @@ std::vector npc_trading::init_selling( npc &np ) } } - item *weapon = np.get_wielded_item(); + item &weapon = np.get_wielded_item(); if( np.will_exchange_items_freely() && - !weapon->is_null() && - !weapon->has_flag( json_flag_NO_UNWIELD ) + !weapon.is_null() && + !weapon.has_flag( json_flag_NO_UNWIELD ) ) { - result.emplace_back( np, *weapon, np.value( *weapon ), false ); + result.emplace_back( np, weapon, np.value( weapon ), false ); } return result; diff --git a/src/overmap.cpp b/src/overmap.cpp index a0b725631d920..2c44f9c5ec93d 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1240,7 +1240,7 @@ struct mutable_overmap_phase { } ); std::string message = string_format( - "At %s failed to match with neighbours N:%s E:%s S:%s W:%s and constraints %s " + "At %s FAILED to match with neighbours N:%s E:%s S:%s W:%s and constraints %s " "from amongst rules %s", pos.to_string(), om.ter( pos + point_north ).id().str(), om.ter( pos + point_east ).id().str(), @@ -1290,6 +1290,10 @@ struct pos_dir { friend bool operator==( const pos_dir &l, const pos_dir &r ) { return l.p == r.p && l.dir == r.dir; } + + friend bool operator<( const pos_dir &l, const pos_dir &r ) { + return std::tie( l.p, l.dir ) < std::tie( r.p, r.dir ); + } }; namespace std @@ -1320,6 +1324,7 @@ class joins_tracker unsigned join_priority; }; using iterator = std::list::iterator; + using const_iterator = std::list::const_iterator; bool any_unresolved() const { return !unresolved.empty(); @@ -1329,8 +1334,30 @@ class joins_tracker return !postponed.empty(); } + void consistency_check() const { +#if 0 // Enable this to check the class invariants, at the cost of more runtime + // verify that there are no positions in common between the + // resolved and postponed lists + for( const join &j : postponed ) { + auto j_pos = j.where.p; + if( unresolved.any_at( j_pos ) ) { + std::vector unr = unresolved.all_at( j_pos ); + if( unr.empty() ) { + cata_fatal( "inconcistency between all_at and any_at" ); + } else { + const join &unr_j = *unr.front(); + cata_fatal( "postponed and unresolved should be disjoint but are not at " + "%s where unresolved has %s: %s", + j_pos.to_string(), unr_j.where.p.to_string(), unr_j.join_id ); + } + } + } +#endif + } + void add_joins_for( const mutable_overmap_terrain &ter, const tripoint_om_omt &pos, om_direction::type rot ) { + consistency_check(); for( const std::pair &p : ter.joins ) { cube_direction dir = p.first + rot; const std::string &join = p.second; @@ -1338,75 +1365,151 @@ class joins_tracker pos_dir this_side{ pos, dir }; pos_dir other_side = this_side.opposite(); if( !other_side.inbounds() ) { - orphaned.push_back( { this_side, join, 0 } ); + debugmsg( "out of bounds join" ); continue; } - if( resolved_position_index.count( other_side ) ) { + if( resolved.count( other_side ) ) { erase_unresolved( this_side ); - } else if( postponed_points.count( pos ) ) { - postponed.push_back( { other_side, join, 0 } ); } else { + // If there were postponed joins pointing into this point, + // so we need to un-postpone them because it might now be + // possible to satisfy them. + restore_postponed_at( other_side.p ); add_unresolved( other_side, join ); } - add_resolved( this_side, join ); + resolved.add( *this, this_side, join ); } + consistency_check(); } std::pair pick_top_priority() const { cata_assert( any_unresolved() ); - auto priority_it = std::find_if( - unresolved_priority_index.begin(), unresolved_priority_index.end(), + auto priority_it = + std::find_if( unresolved_priority_index.begin(), unresolved_priority_index.end(), []( const cata::flat_set &its ) { return !its.empty(); } ); cata_assert( priority_it != unresolved_priority_index.end() ); auto it = random_entry( *priority_it ); const tripoint_om_omt &pos = it->where.p; + cata_assert( !postponed.any_at( pos ) ); std::pair result( it->where, {} ); - for( cube_direction dir : all_enum_values() ) { - pos_dir key{ pos, dir }; - auto pos_it = unresolved_position_index.find( key ); - if( pos_it != unresolved_position_index.end() ) { - result.second.joins.emplace_back( dir, pos_it->second->join_id ); - } + for( iterator it : unresolved.all_at( pos ) ) { + result.second.joins.emplace_back( it->where.dir, it->join_id ); } return result; } void postpone( const tripoint_om_omt &pos ) { - for( cube_direction dir : all_enum_values() ) { - pos_dir p{ pos, dir }; - auto it = unresolved_position_index.find( p ); - if( it != unresolved_position_index.end() ) { - postponed.push_back( *it->second ); - postponed_points.insert( pos ); - erase_unresolved( p ); - } + consistency_check(); + for( iterator it : unresolved.all_at( pos ) ) { + postponed.add( *it ); + erase_unresolved( it->where ); + } + consistency_check(); + } + void restore_postponed_at( const tripoint_om_omt &pos ) { + for( iterator it : postponed.all_at( pos ) ) { + add_unresolved( it->where, it->join_id ); + postponed.erase( it ); } + consistency_check(); } void restore_postponed() { - for( const join &conn : postponed ) { - add_unresolved( conn.where, conn.join_id ); + consistency_check(); + for( const join &j : postponed ) { + add_unresolved( j.where, j.join_id ); } - postponed_points.clear(); postponed.clear(); } private: - unsigned priority_of( const std::string &conn ) { - auto it = joins->find( conn ); + unsigned priority_of( const std::string &join_id ) const { + auto it = joins->find( join_id ); if( it == joins->end() ) { - debugmsg( "priority for join_id %s not known", conn ); + debugmsg( "priority for join_id %s not known", join_id ); return 0; } return it->second->priority; } - void add_unresolved( const pos_dir &p, const std::string &conn ) { - unsigned priority = priority_of( conn ); - unresolved.push_front( { p, conn, priority } ); - auto it = unresolved.begin(); - auto insert_result = unresolved_position_index.emplace( p, it ); - cata_assert( insert_result.second ); + struct indexed_joins { + std::list joins; + std::unordered_map position_index; + + iterator begin() { + return joins.begin(); + } + + iterator end() { + return joins.end(); + } + + const_iterator begin() const { + return joins.begin(); + } + + const_iterator end() const { + return joins.end(); + } + + bool empty() const { + return joins.empty(); + } + + bool count( const pos_dir &p ) const { + return position_index.count( p ); + } + + bool any_at( const tripoint_om_omt &pos ) const { + for( cube_direction dir : all_enum_values() ) { + if( count( pos_dir{ pos, dir } ) ) { + return true; + } + } + return false; + } + + std::vector all_at( const tripoint_om_omt &pos ) const { + std::vector result; + for( cube_direction dir : all_enum_values() ) { + pos_dir key{ pos, dir }; + auto pos_it = position_index.find( key ); + if( pos_it != position_index.end() ) { + result.push_back( pos_it->second ); + } + } + return result; + } + + iterator add( const joins_tracker &tracker, const pos_dir &p, + const std::string &join_id ) { + unsigned priority = tracker.priority_of( join_id ); + return add( { p, join_id, priority } ); + } + + iterator add( const join &j ) { + joins.push_front( j ); + auto it = joins.begin(); + auto insert_result = position_index.emplace( j.where, it ); + cata_assert( insert_result.second ); + return it; + } + + void erase( const iterator it ) { + size_t erased = position_index.erase( it->where ); + cata_assert( erased ); + joins.erase( it ); + } + + void clear() { + joins.clear(); + position_index.clear(); + } + }; + + void add_unresolved( const pos_dir &p, const std::string &join_id ) { + iterator it = unresolved.add( *this, p, join_id ); + unsigned priority = it->join_priority; if( unresolved_priority_index.size() <= priority ) { unresolved_priority_index.resize( priority + 1 ); } @@ -1415,45 +1518,29 @@ class joins_tracker } void erase_unresolved( const pos_dir &p ) { - auto pos_it = unresolved_position_index.find( p ); - cata_assert( pos_it != unresolved_position_index.end() ); + auto pos_it = unresolved.position_index.find( p ); + cata_assert( pos_it != unresolved.position_index.end() ); iterator it = pos_it->second; unsigned priority = it->join_priority; cata_assert( priority < unresolved_priority_index.size() ); size_t erased = unresolved_priority_index[priority].erase( it ); cata_assert( erased ); - unresolved_position_index.erase( pos_it ); unresolved.erase( it ); } - void add_resolved( const pos_dir &p, const std::string &conn ) { - unsigned priority = priority_of( conn ); - resolved.push_front( { p, conn, priority } ); - auto it = resolved.begin(); - bool inserted = resolved_position_index.emplace( p, it ).second; - cata_assert( inserted ); - } - struct compare_iterators { bool operator()( iterator l, iterator r ) { - std::less<> c; - return c( &*l, &*r ); + return l->where < r->where; } }; const std::unordered_map *joins; - std::list unresolved; - std::unordered_map unresolved_position_index; + indexed_joins unresolved; std::vector> unresolved_priority_index; - std::list resolved; - std::unordered_map resolved_position_index; - - std::unordered_set postponed_points; - std::vector postponed; - - std::vector orphaned; + indexed_joins resolved; + indexed_joins postponed; }; struct mutable_overmap_special_data { @@ -1480,12 +1567,12 @@ struct mutable_overmap_special_data { } } for( size_t i = 0; i != joins_vec.size(); ++i ) { - mutable_overmap_join &conn = joins_vec[i]; - if( conn.into_locations.empty() ) { - conn.into_locations = default_locations; + mutable_overmap_join &join = joins_vec[i]; + if( join.into_locations.empty() ) { + join.into_locations = default_locations; } - conn.priority = i; - joins.emplace( conn.id, &conn ); + join.priority = i; + joins.emplace( join.id, &join ); } } @@ -1504,9 +1591,9 @@ struct mutable_overmap_special_data { } } for( const std::pair &p : ter.joins ) { - const std::string &conn = p.second; - if( !joins.count( conn ) ) { - debugmsg( "invalid join id %s in %s", conn, context ); + const std::string &join_id = p.second; + if( !joins.count( join_id ) ) { + debugmsg( "invalid join id %s in %s", join_id, context ); } } } @@ -1581,6 +1668,8 @@ struct mutable_overmap_special_data { if( current_phase == phases.end() ) { break; } + descriptions.push_back( + string_format( "## Entering phase %td", current_phase - phases.begin() ) ); phase_remaining = *current_phase; unresolved.restore_postponed(); } diff --git a/src/overmap.h b/src/overmap.h index 45a9eac019301..5224085562d87 100644 --- a/src/overmap.h +++ b/src/overmap.h @@ -479,7 +479,6 @@ class overmap // Polishing bool check_ot( const std::string &otype, ot_match_type match_type, const tripoint_om_omt &p ) const; - private: bool check_overmap_special_type( const overmap_special_id &id, const tripoint_om_omt &location ) const; cata::optional overmap_special_at( const tripoint_om_omt &p ) const; @@ -497,6 +496,7 @@ class overmap std::vector place_special( const overmap_special &special, const tripoint_om_omt &p, om_direction::type dir, const city &cit, bool must_be_unexplored, bool force ); + private: /** * Iterate over the overmap and place the quota of specials. * If the stated minimums are not reached, it will spawn a new nearby overmap diff --git a/src/overmapbuffer.cpp b/src/overmapbuffer.cpp index af85317ab12fc..d7cccff9fd93e 100644 --- a/src/overmapbuffer.cpp +++ b/src/overmapbuffer.cpp @@ -1234,10 +1234,7 @@ shared_ptr_fast overmapbuffer::remove_npc( const character_id &id ) std::vector> overmapbuffer::get_npcs_near_player( int radius ) { - const tripoint_abs_sm plpos = get_player_character().global_sm_location(); - // INT_MIN is a (a bit ugly) way to inform get_npcs_near not to filter by z-level - const int zpos = get_map().has_zlevels() ? INT_MIN : plpos.z(); - return get_npcs_near( tripoint_abs_sm( plpos.xy(), zpos ), radius ); + return get_npcs_near( get_player_character().global_sm_location(), radius ); } std::vector overmapbuffer::get_overmaps_near( const tripoint_abs_sm &location, @@ -1287,7 +1284,6 @@ std::vector> overmapbuffer::get_companion_mission_npcs( int return available; } -// If z == INT_MIN, allow all z-levels std::vector> overmapbuffer::get_npcs_near( const tripoint_abs_sm &p, int radius ) { @@ -1296,9 +1292,6 @@ std::vector> overmapbuffer::get_npcs_near( const tripoint_a auto temp = it->get_npcs( [&]( const npc & guy ) { // Global position of NPC, in submap coordinates const tripoint_abs_sm pos = guy.global_sm_location(); - if( p.z() != INT_MIN && pos.z() != p.z() ) { - return false; - } return square_dist( p.xy(), pos.xy() ) <= radius; } ); result.insert( result.end(), temp.begin(), temp.end() ); @@ -1306,7 +1299,6 @@ std::vector> overmapbuffer::get_npcs_near( const tripoint_a return result; } -// If z == INT_MIN, allow all z-levels std::vector> overmapbuffer::get_npcs_near_omt( const tripoint_abs_omt &p, int radius ) { @@ -1315,9 +1307,6 @@ std::vector> overmapbuffer::get_npcs_near_omt( const tripoi auto temp = it->get_npcs( [&]( const npc & guy ) { // Global position of NPC, in submap coordinates tripoint_abs_omt pos = guy.global_omt_location(); - if( p.z() != INT_MIN && pos.z() != p.z() ) { - return false; - } return square_dist( p.xy(), pos.xy() ) <= radius; } ); result.insert( result.end(), temp.begin(), temp.end() ); diff --git a/src/overmapbuffer.h b/src/overmapbuffer.h index 0f5e87f9b0dcc..9b8c3d3f1d447 100644 --- a/src/overmapbuffer.h +++ b/src/overmapbuffer.h @@ -245,7 +245,7 @@ class overmapbuffer cata::optional find_camp( const point_abs_omt &p ); /** * Get all npcs in a area with given radius around given central point. - * Only npcs on the given z-level are considered. + * All z-levels are considered. * Uses square_dist for distance calculation. * @param p Central point in submap coordinates. * @param radius Maximal distance of npc from (x,y). If the npc @@ -262,9 +262,9 @@ class overmapbuffer std::vector> get_companion_mission_npcs( int range = 100 ); /** * Uses overmap terrain coordinates, this also means radius is - * in overmap terrain. + * in overmap terrain. All z-levels are considered. * A radius of 0 returns all npcs that are on that specific - * overmap terrain tile. + * overmap terrain tile or above/below. */ std::vector> get_npcs_near_omt( const tripoint_abs_omt &p, int radius ); /** diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index fb1adac8349f4..205738312555c 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -119,10 +119,6 @@ struct pathfinder { // return false if it could not find a suitable point static bool vertical_move_destination( const map &m, ter_furn_flag flag, tripoint &t ) { - if( !m.has_zlevels() ) { - return false; - } - const auto &pf_cache = m.get_pathfinding_cache_ref( t.z ); for( const point &p : closest_points_first( t.xy(), SEEX ) ) { if( pf_cache.special[p.x][p.y] & PF_UPDOWN ) { @@ -133,7 +129,6 @@ static bool vertical_move_destination( const map &m, ter_furn_flag flag, tripoin } } } - return false; } @@ -375,12 +370,12 @@ std::vector map::route( const tripoint &f, const tripoint &t, } } - if( trapavoid && p_special & PF_TRAP ) { + if( trapavoid && ( p_special & PF_TRAP ) ) { const auto &ter_trp = terrain.trap.obj(); const auto &trp = ter_trp.is_benign() ? tile.get_trap_t() : ter_trp; if( !trp.is_benign() ) { // For now make them detect all traps - if( has_zlevels() && terrain.has_flag( ter_furn_flag::TFLAG_NO_FLOOR ) ) { + if( terrain.has_flag( ter_furn_flag::TFLAG_NO_FLOOR ) ) { // Special case - ledge in z-levels // Warning: really expensive, needs a cache if( valid_move( p, tripoint( p.xy(), p.z - 1 ), false, true ) ) { @@ -418,7 +413,7 @@ std::vector map::route( const tripoint &f, const tripoint &t, } } - if( !has_zlevels() || !( cur_special & PF_UPDOWN ) || !settings.allow_climb_stairs ) { + if( !( cur_special & PF_UPDOWN ) || !settings.allow_climb_stairs ) { // The part below is only for z-level pathing continue; } diff --git a/src/pickup.cpp b/src/pickup.cpp index b53a71abffd73..3e765458826ba 100644 --- a/src/pickup.cpp +++ b/src/pickup.cpp @@ -148,11 +148,11 @@ static pickup_answer handle_problematic_pickup( const item &it, bool &offered_sw amenu.text = explain; offered_swap = true; - const item *weapon = u.get_wielded_item(); + const item &weapon = u.get_wielded_item(); // TODO: Gray out if not enough hands if( u.has_wield_conflicts( it ) ) { - amenu.addentry( WIELD, u.can_unwield( *weapon ).success(), 'w', - _( "Dispose of %s and wield %s" ), weapon->display_name(), + amenu.addentry( WIELD, u.can_unwield( weapon ).success(), 'w', + _( "Dispose of %s and wield %s" ), weapon.display_name(), it.display_name() ); } else { amenu.addentry( WIELD, true, 'w', _( "Wield %s" ), it.display_name() ); @@ -310,12 +310,12 @@ bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool &offer const auto wield_check = player_character.can_wield( newit ); if( wield_check.success() ) { picked_up = player_character.wield( newit ); - const item *weapon = player_character.get_wielded_item(); - if( weapon->invlet ) { - add_msg( m_info, _( "Wielding %c - %s" ), weapon->invlet, - weapon->display_name() ); + const item &weapon = player_character.get_wielded_item(); + if( weapon.invlet ) { + add_msg( m_info, _( "Wielding %c - %s" ), weapon.invlet, + weapon.display_name() ); } else { - add_msg( m_info, _( "Wielding - %s" ), player_character.get_wielded_item()->display_name() ); + add_msg( m_info, _( "Wielding - %s" ), player_character.get_wielded_item().display_name() ); } } else { add_msg( m_neutral, wield_check.c_str() ); @@ -344,9 +344,9 @@ bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool &offer // failed to add, fill pockets if it's a stack if( newit.count_by_charges() ) { int remaining_charges = newit.charges; - item *weapon = player_character.get_wielded_item(); - if( weapon->can_contain_partial( newit ) ) { - int used_charges = weapon->fill_with( newit, remaining_charges ); + item &weapon = player_character.get_wielded_item(); + if( weapon.can_contain_partial( newit ) ) { + int used_charges = weapon.fill_with( newit, remaining_charges ); remaining_charges -= used_charges; } for( item &i : player_character.worn ) { diff --git a/src/player_hardcoded_effects.cpp b/src/player_hardcoded_effects.cpp index 4bc410f7a3b36..77958b7e5f2fe 100644 --- a/src/player_hardcoded_effects.cpp +++ b/src/player_hardcoded_effects.cpp @@ -1605,7 +1605,7 @@ void Character::hardcoded_effects( effect &it ) mod_dex_bonus( -8 ); recoil = MAX_RECOIL; } else if( limb == "hand" ) { - if( is_armed() && can_drop( *get_wielded_item() ).success() ) { + if( is_armed() && can_drop( get_wielded_item() ).success() ) { if( dice( 4, 4 ) > get_dex() ) { cancel_activity(); //Prevent segfaults from activities trying to access missing item put_into_vehicle_or_drop( *this, item_drop_reason::tumbling, { remove_weapon() } ); diff --git a/src/ranged.cpp b/src/ranged.cpp index aa4bc7f492f7c..615d9b7b0e7c0 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -717,7 +717,7 @@ void npc::pretend_fire( npc *source, int shots, item &gun ) int Character::fire_gun( const tripoint &target, int shots ) { - return fire_gun( target, shots, *get_wielded_item() ); + return fire_gun( target, shots, get_wielded_item() ); } int Character::fire_gun( const tripoint &target, int shots, item &gun ) @@ -2050,7 +2050,7 @@ target_handler::trajectory target_ui::run() map &here = get_map(); // Load settings - allow_zlevel_shift = here.has_zlevels() && get_option( "FOV_3D" ); + allow_zlevel_shift = get_option( "FOV_3D" ); snap_to_target = get_option( "SNAP_TO_TARGET" ); if( mode == TargetMode::Turrets ) { // Due to how cluttered the display would become, disable it by default diff --git a/src/savegame.cpp b/src/savegame.cpp index ddb2abd27c191..ab4ddb22b99e2 100644 --- a/src/savegame.cpp +++ b/src/savegame.cpp @@ -95,8 +95,6 @@ void game::serialize( std::ostream &fout ) // Then each monster json.member( "active_monsters", *critter_tracker ); - json.member( "stair_monsters", coming_to_stairs ); - json.member( "monstairz", monstairz ); json.member( "driving_view_offset", driving_view_offset ); json.member( "turnssincelastmon", turnssincelastmon ); @@ -211,13 +209,8 @@ void game::unserialize( std::istream &fin, const std::string &path ) } data.read( "active_monsters", *critter_tracker ); - coming_to_stairs.clear(); - for( JsonValue elem : data.get_array( "stair_monsters" ) ) { - monster stairtmp; - elem.read( stairtmp ); - coming_to_stairs.push_back( stairtmp ); - } - data.read( "monstairz", monstairz ); + data.has_null( "stair_monsters" ); // TEMPORARY until 0.G + data.has_null( "monstairz" ); // TEMPORARY until 0.G data.read( "driving_view_offset", driving_view_offset ); data.read( "turnssincelastmon", turnssincelastmon ); @@ -682,7 +675,7 @@ void overmap::unserialize( std::istream &fin ) std::string name = jsin.get_member_name(); if( name == "special" ) { jsin.read( s ); - is_safe_zone = s->has_flag( "SAFE_AT_WORLDGEN" ) > 0; + is_safe_zone = s->has_flag( "SAFE_AT_WORLDGEN" ); } else if( name == "placements" ) { jsin.start_array(); while( !jsin.end_array() ) { diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 254680e93126a..197a0e7fc6724 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -2280,7 +2280,6 @@ void monster::load( const JsonObject &data ) data.read( "anger", anger ); data.read( "morale", morale ); data.read( "hallucination", hallucination ); - data.read( "stairscount", staircount ); // really? data.read( "fish_population", fish_population ); data.read( "summon_time_limit", summon_time_limit ); @@ -2351,7 +2350,6 @@ void monster::store( JsonOut &json ) const json.member( "anger", anger ); json.member( "morale", morale ); json.member( "hallucination", hallucination ); - json.member( "stairscount", staircount ); if( tied_item ) { json.member( "tied_item", *tied_item ); } diff --git a/src/sdltiles.cpp b/src/sdltiles.cpp index d2b4979ea76cb..2bb0bb1f31135 100644 --- a/src/sdltiles.cpp +++ b/src/sdltiles.cpp @@ -2264,7 +2264,7 @@ void remove_stale_inventory_quick_shortcuts() } if( !in_inventory ) { // We couldn't find it in worn items either, check weapon held - if( player_character.get_wielded_item()->invlet == key ) { + if( player_character.get_wielded_item().invlet == key ) { in_inventory = true; } } @@ -2399,8 +2399,8 @@ void draw_quick_shortcuts() } if( hint_text == "none" ) { // We couldn't find it in worn items either, must be weapon held - if( player_character.get_wielded_item()->invlet == key ) { - hint_text = player_character.get_wielded_item()->display_name(); + if( player_character.get_wielded_item().invlet == key ) { + hint_text = player_character.get_wielded_item().display_name(); } } } else { @@ -2773,8 +2773,8 @@ static void CheckMessages() actions.insert( ACTION_CYCLE_MOVE ); } // Only prioritize fire weapon options if we're wielding a ranged weapon. - if( player_character.get_wielded_item()->is_gun() || - player_character.get_wielded_item()->has_flag( flag_REACH_ATTACK ) ) { + if( player_character.get_wielded_item().is_gun() || + player_character.get_wielded_item().has_flag( flag_REACH_ATTACK ) ) { actions.insert( ACTION_FIRE ); } } diff --git a/src/suffer.cpp b/src/suffer.cpp index 18199a8e15848..2c1be6fd03392 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -437,11 +437,11 @@ void suffer::from_chemimbalance( Character &you ) void suffer::from_schizophrenia( Character &you ) { std::string i_name_w; - if( !you.get_wielded_item()->is_null() ) { - i_name_w = you.get_wielded_item()->has_var( "item_label" ) ? - you.get_wielded_item()->get_var( "item_label" ) : + if( !you.get_wielded_item().is_null() ) { + i_name_w = you.get_wielded_item().has_var( "item_label" ) ? + you.get_wielded_item().get_var( "item_label" ) : //~ %1$s: weapon name - string_format( _( "your %1$s" ), you.get_wielded_item()->type_name() ); + string_format( _( "your %1$s" ), you.get_wielded_item().type_name() ); } // Start with the effects that both NPCs and avatars can suffer from // Delusions @@ -498,14 +498,14 @@ void suffer::from_schizophrenia( Character &you ) return; } // Drop weapon - if( one_turn_in( 2_days ) && !you.get_wielded_item()->is_null() ) { + if( one_turn_in( 2_days ) && !you.get_wielded_item().is_null() ) { const translation snip = SNIPPET.random_from_category( "schizo_weapon_drop" ).value_or( translation() ); std::string str = string_format( snip, i_name_w ); str[0] = toupper( str[0] ); you.add_msg_if_player( m_bad, "%s", str ); - item_location loc( you, you.get_wielded_item() ); + item_location loc( you, &you.get_wielded_item() ); you.drop( loc, you.pos() ); return; } @@ -581,7 +581,7 @@ void suffer::from_schizophrenia( Character &you ) } // Talking weapon - if( !you.get_wielded_item()->is_null() ) { + if( !you.get_wielded_item().is_null() ) { // If player has a weapon, picks a message from said weapon // Weapon tells player to kill a monster if any are nearby // Weapon is concerned for player if bleeding @@ -609,7 +609,7 @@ void suffer::from_schizophrenia( Character &you ) i_talk_w = SNIPPET.random_from_category( "schizo_weapon_talk_bleeding" ).value_or( translation() ).translated(); does_talk = true; - } else if( you.get_wielded_item()->damage() >= you.get_wielded_item()->max_damage() / 3 && + } else if( you.get_wielded_item().damage() >= you.get_wielded_item().max_damage() / 3 && one_turn_in( 1_hours ) ) { i_talk_w = SNIPPET.random_from_category( "schizo_weapon_talk_damaged" ).value_or( translation() ).translated(); @@ -858,7 +858,7 @@ void suffer::from_sunburn( Character &you ) } } // Umbrellas can keep the sun off the skin - if( you.get_wielded_item()->has_flag( flag_RAIN_PROTECT ) ) { + if( you.get_wielded_item().has_flag( flag_RAIN_PROTECT ) ) { return; } @@ -1204,14 +1204,14 @@ void suffer::from_bad_bionics( Character &you ) you.moves -= 150; you.mod_power_level( -bio_dis_shock->power_trigger ); - if( you.get_wielded_item()->typeId() == itype_e_handcuffs && you.get_wielded_item()->charges > 0 ) { - you.get_wielded_item()->charges -= rng( 1, 3 ) * 50; - if( you.get_wielded_item()->charges < 1 ) { - you.get_wielded_item()->charges = 1; + if( you.get_wielded_item().typeId() == itype_e_handcuffs && you.get_wielded_item().charges > 0 ) { + you.get_wielded_item().charges -= rng( 1, 3 ) * 50; + if( you.get_wielded_item().charges < 1 ) { + you.get_wielded_item().charges = 1; } you.add_msg_if_player( m_good, _( "The %s seems to be affected by the discharge." ), - you.get_wielded_item()->tname() ); + you.get_wielded_item().tname() ); } sfx::play_variant_sound( "bionics", "elec_discharge", 100 ); } diff --git a/src/talker_character.cpp b/src/talker_character.cpp index 66fe92e2be202..288d7091b4bae 100644 --- a/src/talker_character.cpp +++ b/src/talker_character.cpp @@ -305,7 +305,7 @@ bool talker_character::unarmed_attack() const bool talker_character::can_stash_weapon() const { - return me_chr->can_pickVolume( *me_chr->get_wielded_item() ); + return me_chr->can_pickVolume( me_chr->get_wielded_item() ); } bool talker_character::has_stolen_item( const talker &guy ) const @@ -397,7 +397,7 @@ bool talker_character::worn_with_flag( const flag_id &flag ) const bool talker_character::wielded_with_flag( const flag_id &flag ) const { - return me_chr->get_wielded_item()->has_flag( flag ); + return me_chr->get_wielded_item().has_flag( flag ); } units::energy talker_character::power_cur() const diff --git a/src/talker_npc.cpp b/src/talker_npc.cpp index 6e49c41a2e733..fbef2c31d7f72 100644 --- a/src/talker_npc.cpp +++ b/src/talker_npc.cpp @@ -508,7 +508,7 @@ std::string talker_npc::give_item_to( const bool to_use ) } item &given = *loc; - if( ( &given == player_character.get_wielded_item() && + if( ( &given == &player_character.get_wielded_item() && given.has_flag( STATIC( flag_id( "NO_UNWIELD" ) ) ) ) || ( player_character.is_worn( given ) && given.has_flag( STATIC( flag_id( "NO_TAKEOFF" ) ) ) ) ) { @@ -522,13 +522,13 @@ std::string talker_npc::give_item_to( const bool to_use ) bool taken = false; std::string reason = _( "Nope." ); - const item *weapon = me_npc->get_wielded_item(); - int our_ammo = me_npc->ammo_count_for( *weapon ); + const item &weapon = me_npc->get_wielded_item(); + int our_ammo = me_npc->ammo_count_for( weapon ); int new_ammo = me_npc->ammo_count_for( given ); const double new_weapon_value = me_npc->weapon_value( given, new_ammo ); - const double cur_weapon_value = me_npc->weapon_value( *weapon, our_ammo ); + const double cur_weapon_value = me_npc->weapon_value( weapon, our_ammo ); add_msg_debug( debugmode::DF_TALKER, "NPC evaluates own %s (%d ammo): %0.1f", - weapon->typeId().str(), our_ammo, cur_weapon_value ); + weapon.typeId().str(), our_ammo, cur_weapon_value ); add_msg_debug( debugmode::DF_TALKER, "NPC evaluates your %s (%d ammo): %0.1f", given.typeId().str(), new_ammo, new_weapon_value ); if( to_use ) { diff --git a/src/trapfunc.cpp b/src/trapfunc.cpp index 1fd31e2131b49..4de38eb3a7dd6 100644 --- a/src/trapfunc.cpp +++ b/src/trapfunc.cpp @@ -1160,32 +1160,6 @@ bool trapfunc::ledge( const tripoint &p, Creature *c, item * ) return false; } map &here = get_map(); - if( !here.has_zlevels() ) { - if( c->is_avatar() ) { - add_msg( m_warning, _( "You fall down a level!" ) ); - g->vertical_move( -1, true ); - if( c->has_trait( trait_WINGS_BIRD ) || ( one_in( 2 ) && - c->has_trait( trait_WINGS_BUTTERFLY ) ) ) { - add_msg( _( "You flap your wings and flutter down gracefully." ) ); - } else if( c->as_character()->has_active_bionic( bio_shock_absorber ) ) { - add_msg( m_info, - _( "You hit the ground hard, but your shock absorbers handle the impact admirably!" ) ); - } else { - c->as_avatar()->impact( 20, p ); - } - } else { - c->add_msg_if_npc( _( " falls down a level!" ) ); - tripoint dest = c->pos(); - dest.z--; - c->impact( 20, dest ); - c->setpos( dest ); - if( m != nullptr ) { - g->despawn_monster( *m ); - } - } - - return true; - } int height = 0; tripoint where = p; diff --git a/src/vehicle_move.cpp b/src/vehicle_move.cpp index 804981c230501..c8958a99e4c1f 100644 --- a/src/vehicle_move.cpp +++ b/src/vehicle_move.cpp @@ -1304,8 +1304,7 @@ bool vehicle::check_heli_descend( Character &p ) creature_tracker &creatures = get_creature_tracker(); for( const tripoint &pt : get_points( true ) ) { tripoint below( pt.xy(), pt.z - 1 ); - if( here.has_zlevels() && ( pt.z < -OVERMAP_DEPTH || - !here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, pt ) ) ) { + if( pt.z < -OVERMAP_DEPTH || !here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, pt ) ) { p.add_msg_if_player( _( "You are already landed!" ) ); return false; } @@ -1893,7 +1892,7 @@ vehicle *vehicle::act_on_map() bool vehicle::level_vehicle() { map &here = get_map(); - if( !here.has_zlevels() || ( is_flying && is_rotorcraft() ) ) { + if( is_flying && is_rotorcraft() ) { return true; } // make sure that all parts are either supported across levels or on the same level @@ -1940,9 +1939,6 @@ bool vehicle::level_vehicle() void vehicle::check_falling_or_floating() { - map &here = get_map(); - is_falling = here.has_zlevels(); - // If we're flying none of the rest of this matters. if( is_flying && is_rotorcraft() ) { is_falling = false; @@ -1950,7 +1946,10 @@ void vehicle::check_falling_or_floating() in_water = false; return; } + + is_falling = true; is_flying = false; + map &here = get_map(); auto has_support = [&here]( const tripoint & position, const bool water_supports ) { // if we're at the bottom of the z-levels, we're supported diff --git a/src/weather.cpp b/src/weather.cpp index 784f3544e2e37..bc31b10c79341 100644 --- a/src/weather.cpp +++ b/src/weather.cpp @@ -407,7 +407,7 @@ void wet_character( Character &target, int amount ) { if( amount <= 0 || target.has_trait( trait_FEATHERS ) || - target.get_wielded_item()->has_flag( json_flag_RAIN_PROTECT ) || + target.get_wielded_item().has_flag( json_flag_RAIN_PROTECT ) || ( !one_in( 50 ) && target.worn_with_flag( json_flag_RAINPROOF ) ) ) { return; } diff --git a/tests/active_item_test.cpp b/tests/active_item_test.cpp index 1d09b2cce3431..a54eee69c65ca 100644 --- a/tests/active_item_test.cpp +++ b/tests/active_item_test.cpp @@ -30,7 +30,7 @@ TEST_CASE( "active_items_processed_regularly", "[item]" ) bool wield_success = player_character.wield( active_item ); REQUIRE( wield_success ); - REQUIRE( player_character.get_wielded_item()->charges == active_item_ticks ); + REQUIRE( player_character.get_wielded_item().charges == active_item_ticks ); here.add_item( player_character.pos(), active_item ); REQUIRE( here.i_at( player_character.pos() ).only_item().charges == active_item_ticks ); @@ -42,6 +42,6 @@ TEST_CASE( "active_items_processed_regularly", "[item]" ) const int expected_ticks = active_item_ticks - 1; CHECK( inventory_item->charges == expected_ticks ); - CHECK( player_character.get_wielded_item()->charges == expected_ticks ); + CHECK( player_character.get_wielded_item().charges == expected_ticks ); CHECK( here.i_at( player_character.pos() ).only_item().charges == expected_ticks ); } diff --git a/tests/char_suffer_test.cpp b/tests/char_suffer_test.cpp index de00129886a23..1702706d0146b 100644 --- a/tests/char_suffer_test.cpp +++ b/tests/char_suffer_test.cpp @@ -140,7 +140,7 @@ TEST_CASE( "suffering from albinism", "[char][suffer][albino]" ) WHEN( "wielding an umbrella and wearing sunglasses" ) { dummy.wield( umbrella ); - REQUIRE( dummy.get_wielded_item()->has_flag( flag_RAIN_PROTECT ) ); + REQUIRE( dummy.get_wielded_item().has_flag( flag_RAIN_PROTECT ) ); dummy.wear_item( shades, false ); REQUIRE( dummy.worn_with_flag( flag_SUN_GLASSES ) ); @@ -240,7 +240,7 @@ TEST_CASE( "suffering from sunburn", "[char][suffer][sunburn]" ) WHEN( "naked and wielding an umbrella, with or without sunglasses" ) { dummy.worn.clear(); dummy.wield( umbrella ); - REQUIRE( dummy.get_wielded_item()->has_flag( flag_RAIN_PROTECT ) ); + REQUIRE( dummy.get_wielded_item().has_flag( flag_RAIN_PROTECT ) ); // Umbrella completely shields the skin from exposure when wielded THEN( "they suffer no injury" ) { diff --git a/tests/crafting_test.cpp b/tests/crafting_test.cpp index 0614ffa21259a..503adc28b2fc7 100644 --- a/tests/crafting_test.cpp +++ b/tests/crafting_test.cpp @@ -646,20 +646,20 @@ static void verify_inventory( const std::vector &has, for( const item *i : player_character.inv_dump() ) { os << " " << i->typeId().str() << " (" << i->charges << ")\n"; } - os << "Wielded:\n" << player_character.get_wielded_item()->tname() << "\n"; + os << "Wielded:\n" << player_character.get_wielded_item().tname() << "\n"; INFO( os.str() ); for( const std::string &i : has ) { INFO( "expecting " << i ); const bool has_item = player_has_item_of_type( i ) || - player_character.get_wielded_item()->type->get_id() == itype_id( i ); + player_character.get_wielded_item().type->get_id() == itype_id( i ); REQUIRE( has_item ); } for( const std::string &i : hasnt ) { INFO( "not expecting " << i ); const bool hasnt_item = !player_has_item_of_type( i ) && - !( player_character.get_wielded_item()->type->get_id() == itype_id( i ) ); + !( player_character.get_wielded_item().type->get_id() == itype_id( i ) ); REQUIRE( hasnt_item ); } } diff --git a/tests/invlet_test.cpp b/tests/invlet_test.cpp index 0ec2b8656c713..10f3e737360e8 100644 --- a/tests/invlet_test.cpp +++ b/tests/invlet_test.cpp @@ -359,7 +359,7 @@ static void move_item( Character &you, const int id, const inventory_location fr wear_from_feet( you, id ); break; case WIELDED_OR_WORN: - if( you.get_wielded_item()->is_null() ) { + if( you.get_wielded_item().is_null() ) { wield_from_feet( you, id ); } else { // since we can only wield one item, wear the item instead @@ -381,7 +381,7 @@ static void move_item( Character &you, const int id, const inventory_location fr you.wear( item_location( *you.as_character(), &item_at( you, id, from ) ), false ); break; case WIELDED_OR_WORN: - if( you.get_wielded_item()->is_null() ) { + if( you.get_wielded_item().is_null() ) { you.wield( item_at( you, id, from ) ); } else { // since we can only wield one item, wear the item instead diff --git a/tests/item_test.cpp b/tests/item_test.cpp index dc84715a5617e..9d12d64cad4ae 100644 --- a/tests/item_test.cpp +++ b/tests/item_test.cpp @@ -512,7 +512,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" THEN( "should get wet from water" ) { g->water_affect_items( guy ); - CHECK( guy.get_wielded_item()->wetness > 0 ); + CHECK( guy.get_wielded_item().wetness > 0 ); } } @@ -529,7 +529,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" THEN( "should get wet from water" ) { g->water_affect_items( guy ); - const item *test_item = guy.get_wielded_item()->all_items_top().front(); + const item *test_item = guy.get_wielded_item().all_items_top().front(); REQUIRE( test_item->typeId() == itype_test_mp3 ); CHECK( test_item->wetness > 0 ); } @@ -548,7 +548,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" THEN( "should not be broken by water" ) { g->water_affect_items( guy ); - const item *test_item = guy.get_wielded_item()->all_items_top().front(); + const item *test_item = guy.get_wielded_item().all_items_top().front(); REQUIRE( test_item->typeId() == itype_test_mp3 ); CHECK( test_item->wetness == 0 ); } @@ -569,7 +569,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" THEN( "should get wet from water" ) { g->water_affect_items( guy ); - const item *test_item = guy.get_wielded_item()->all_items_top().front()->all_items_top().front(); + const item *test_item = guy.get_wielded_item().all_items_top().front()->all_items_top().front(); REQUIRE( test_item->typeId() == itype_test_mp3 ); CHECK( test_item->wetness > 0 ); } @@ -590,7 +590,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" THEN( "should not be broken by water" ) { g->water_affect_items( guy ); - const item *test_item = guy.get_wielded_item()->all_items_top().front()->all_items_top().front(); + const item *test_item = guy.get_wielded_item().all_items_top().front()->all_items_top().front(); REQUIRE( test_item->typeId() == itype_test_mp3 ); CHECK( test_item->wetness == 0 ); } @@ -606,7 +606,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" THEN( "should be wet for around 8664 seconds" ) { g->water_affect_items( guy ); - CHECK( guy.get_wielded_item()->wetness == Approx( 8664 ).margin( 20 ) ); + CHECK( guy.get_wielded_item().wetness == Approx( 8664 ).margin( 20 ) ); } } @@ -625,7 +625,7 @@ TEST_CASE( "water affect items while swimming check", "[item][water][swimming]" g->water_affect_items( guy ); g->water_affect_items( guy ); AND_THEN( "should be wet for around 43320 seconds" ) { - CHECK( guy.get_wielded_item()->wetness == Approx( 43320 ).margin( 100 ) ); + CHECK( guy.get_wielded_item().wetness == Approx( 43320 ).margin( 100 ) ); } } } diff --git a/tests/npc_attack_test.cpp b/tests/npc_attack_test.cpp index 3256d8344fe6e..c595ed1aa0643 100644 --- a/tests/npc_attack_test.cpp +++ b/tests/npc_attack_test.cpp @@ -66,7 +66,7 @@ TEST_CASE( "NPC faces zombies", "[npc_attack]" ) WHEN( "NPC only has a chef knife" ) { item weapon( "knife_chef" ); main_npc.set_wielded_item( weapon ); - REQUIRE( main_npc.get_wielded_item()->typeId() == itype_id( "knife_chef" ) ); + REQUIRE( main_npc.get_wielded_item().typeId() == itype_id( "knife_chef" ) ); THEN( "NPC attempts to melee the enemy target" ) { main_npc.evaluate_best_weapon( zombie ); @@ -125,7 +125,7 @@ TEST_CASE( "NPC faces zombies", "[npc_attack]" ) WHEN( "NPC only has a bunch of rocks" ) { item weapon( "rock" ); main_npc.set_wielded_item( weapon ); - REQUIRE( main_npc.get_wielded_item()->typeId() == itype_id( "rock" ) ); + REQUIRE( main_npc.get_wielded_item().typeId() == itype_id( "rock" ) ); THEN( "NPC doesn't bother throwing the rocks so close" ) { main_npc.evaluate_best_weapon( zombie ); @@ -141,7 +141,7 @@ TEST_CASE( "NPC faces zombies", "[npc_attack]" ) WHEN( "NPC only has a chef knife" ) { item weapon( "knife_chef" ); main_npc.set_wielded_item( weapon ); - REQUIRE( main_npc.get_wielded_item()->typeId() == itype_id( "knife_chef" ) ); + REQUIRE( main_npc.get_wielded_item().typeId() == itype_id( "knife_chef" ) ); THEN( "NPC attempts to melee the enemy target" ) { main_npc.evaluate_best_weapon( zombie ); @@ -158,7 +158,7 @@ TEST_CASE( "NPC faces zombies", "[npc_attack]" ) WHEN( "NPC only has a bunch of rocks" ) { item weapon( "rock" ); main_npc.set_wielded_item( weapon ); - REQUIRE( main_npc.get_wielded_item()->typeId() == itype_id( "rock" ) ); + REQUIRE( main_npc.get_wielded_item().typeId() == itype_id( "rock" ) ); THEN( "NPC throws rocks at the zombie" ) { main_npc.evaluate_best_weapon( zombie ); @@ -175,7 +175,7 @@ TEST_CASE( "NPC faces zombies", "[npc_attack]" ) WHEN( "NPC only has a chef knife" ) { item weapon( "knife_chef" ); main_npc.set_wielded_item( weapon ); - REQUIRE( main_npc.get_wielded_item()->typeId() == itype_id( "knife_chef" ) ); + REQUIRE( main_npc.get_wielded_item().typeId() == itype_id( "knife_chef" ) ); WHEN( "NPC is targetting closest zombie" ) { main_npc.evaluate_best_weapon( zombie ); diff --git a/tests/overmap_test.cpp b/tests/overmap_test.cpp index 98f27650fccac..5ed91a8566c07 100644 --- a/tests/overmap_test.cpp +++ b/tests/overmap_test.cpp @@ -13,7 +13,7 @@ #include "overmapbuffer.h" #include "type_id.h" -TEST_CASE( "set_and_get_overmap_scents" ) +TEST_CASE( "set_and_get_overmap_scents", "[overmap]" ) { std::unique_ptr test_overmap = std::make_unique( point_abs_om() ); @@ -34,7 +34,7 @@ TEST_CASE( "set_and_get_overmap_scents" ) REQUIRE( test_overmap->scent_at( { 75, 85, 0} ).initial_strength == 90 ); } -TEST_CASE( "default_overmap_generation_always_succeeds", "[slow]" ) +TEST_CASE( "default_overmap_generation_always_succeeds", "[overmap][slow]" ) { int overmaps_to_construct = 10; for( const point_abs_om &candidate_addr : closest_points_first( point_abs_om(), 10 ) ) { @@ -58,7 +58,7 @@ TEST_CASE( "default_overmap_generation_always_succeeds", "[slow]" ) overmap_buffer.clear(); } -TEST_CASE( "default_overmap_generation_has_non_mandatory_specials_at_origin", "[slow]" ) +TEST_CASE( "default_overmap_generation_has_non_mandatory_specials_at_origin", "[overmap][slow]" ) { const point_abs_om origin{}; @@ -179,3 +179,29 @@ TEST_CASE( "is_ot_match", "[overmap][terrain]" ) } } +TEST_CASE( "mutable_overmap_placement", "[overmap][slow]" ) +{ + for( int j = 0; j < 100; ++j ) { + overmap om{ point_abs_om( point_zero ) }; + + om_direction::type dir = om_direction::type::north; + const overmap_special &anthill = *overmap_special_id( "test_anthill" ); + const city cit; + + constexpr int num_trials = 100; + int successes = 0; + + for( int i = 0; i < num_trials; ++i ) { + tripoint_om_omt try_pos( rng( 0, OMAPX - 1 ), rng( 0, OMAPY - 1 ), 0 ); + + if( om.can_place_special( anthill, try_pos, dir, false ) ) { + std::vector placed_points = + om.place_special( anthill, try_pos, dir, cit, false, false ); + CHECK( !placed_points.empty() ); + ++successes; + } + } + + CHECK( successes > 50 ); + } +} diff --git a/tests/player_activities_test.cpp b/tests/player_activities_test.cpp index 9922b57f0752f..765938e532b63 100644 --- a/tests/player_activities_test.cpp +++ b/tests/player_activities_test.cpp @@ -407,8 +407,8 @@ TEST_CASE( "shearing", "[activity][shearing][animals]" ) dummy.process_items(); } - CHECK( dummy.get_wielded_item()->ammo_remaining() == 0 ); - REQUIRE( dummy.get_wielded_item()->typeId().str() == itype_test_shears_off.str() ); + CHECK( dummy.get_wielded_item().ammo_remaining() == 0 ); + REQUIRE( dummy.get_wielded_item().typeId().str() == itype_test_shears_off.str() ); CHECK( dummy.max_quality( qual_SHEAR ) <= 0 ); @@ -530,9 +530,9 @@ TEST_CASE( "boltcut", "[activity][boltcut]" ) item it_boltcut( itype_test_boltcutter ); dummy.wield( it_boltcut ); - REQUIRE( dummy.get_wielded_item()->typeId() == itype_test_boltcutter ); + REQUIRE( dummy.get_wielded_item().typeId() == itype_test_boltcutter ); - return item_location{dummy, dummy.get_wielded_item()}; + return item_location{dummy, &dummy.get_wielded_item()}; }; auto setup_activity = [&dummy]( const item_location & torch ) -> void { @@ -656,9 +656,9 @@ TEST_CASE( "boltcut", "[activity][boltcut]" ) it_boltcut_elec.put_in( battery, item_pocket::pocket_type::MAGAZINE_WELL ); dummy.wield( it_boltcut_elec ); - REQUIRE( dummy.get_wielded_item()->typeId() == itype_test_boltcutter_elec ); + REQUIRE( dummy.get_wielded_item().typeId() == itype_test_boltcutter_elec ); - item_location boltcutter_elec{dummy, dummy.get_wielded_item()}; + item_location boltcutter_elec{dummy, &dummy.get_wielded_item()}; setup_activity( boltcutter_elec ); REQUIRE( dummy.activity.id() == ACT_BOLTCUTTING ); @@ -795,10 +795,10 @@ TEST_CASE( "oxytorch", "[activity][oxytorch]" ) it_welding_torch.ammo_set( itype_oxyacetylene ); dummy.wield( it_welding_torch ); - REQUIRE( dummy.get_wielded_item()->typeId() == itype_test_oxytorch ); + REQUIRE( dummy.get_wielded_item().typeId() == itype_test_oxytorch ); REQUIRE( dummy.max_quality( qual_WELD ) == 10 ); - return item_location{dummy, dummy.get_wielded_item()}; + return item_location{dummy, &dummy.get_wielded_item()}; }; auto setup_activity = [&dummy]( const item_location & torch ) -> void { diff --git a/tests/ranged_balance_test.cpp b/tests/ranged_balance_test.cpp index 4c39e8bf499bb..e2b820ee02faa 100644 --- a/tests/ranged_balance_test.cpp +++ b/tests/ranged_balance_test.cpp @@ -126,7 +126,7 @@ static std::vector firing_test( const dispersion_sources &dis static dispersion_sources get_dispersion( npc &shooter, const int aim_time ) { - item &gun = *shooter.get_wielded_item(); + item &gun = shooter.get_wielded_item(); dispersion_sources dispersion = shooter.get_weapon_dispersion( gun ); shooter.moves = aim_time; @@ -152,8 +152,8 @@ static void test_shooting_scenario( npc &shooter, const int min_quickdraw_range, } ); INFO( dispersion ); INFO( "Range: " << min_quickdraw_range ); - INFO( "Max aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), MAX_RECOIL ) ); - INFO( "Min aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), shooter.recoil ) ); + INFO( "Max aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), MAX_RECOIL ) ); + INFO( "Min aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), shooter.recoil ) ); CAPTURE( shooter.ranged_dispersion_modifier_hands() ); CAPTURE( minimum_stats[0].n() ); CAPTURE( minimum_stats[0].margin_of_error() ); @@ -168,8 +168,8 @@ static void test_shooting_scenario( npc &shooter, const int min_quickdraw_range, 0.5 ) ); INFO( dispersion ); INFO( "Range: " << min_good_range ); - INFO( "Max aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), MAX_RECOIL ) ); - INFO( "Min aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), shooter.recoil ) ); + INFO( "Max aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), MAX_RECOIL ) ); + INFO( "Min aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), shooter.recoil ) ); CAPTURE( shooter.ranged_dispersion_modifier_hands() ); CAPTURE( good_stats.n() ); CAPTURE( good_stats.margin_of_error() ); @@ -181,8 +181,8 @@ static void test_shooting_scenario( npc &shooter, const int min_quickdraw_range, 0.1 ) ); INFO( dispersion ); INFO( "Range: " << max_good_range ); - INFO( "Max aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), MAX_RECOIL ) ); - INFO( "Min aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), shooter.recoil ) ); + INFO( "Max aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), MAX_RECOIL ) ); + INFO( "Min aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), shooter.recoil ) ); CAPTURE( shooter.ranged_dispersion_modifier_hands() ); CAPTURE( good_stats.n() ); CAPTURE( good_stats.margin_of_error() ); @@ -201,13 +201,13 @@ static void test_fast_shooting( npc &shooter, const int moves, float hit_rate ) Threshold( accuracy_standard, hit_rate_cap ) ); INFO( dispersion ); INFO( "Range: " << fast_shooting_range ); - INFO( "Max aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), MAX_RECOIL ) ); - INFO( "Min aim speed: " << shooter.aim_per_move( *shooter.get_wielded_item(), shooter.recoil ) ); + INFO( "Max aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), MAX_RECOIL ) ); + INFO( "Min aim speed: " << shooter.aim_per_move( shooter.get_wielded_item(), shooter.recoil ) ); CAPTURE( shooter.ranged_dispersion_modifier_hands() ); - CAPTURE( shooter.get_wielded_item()->gun_skill().str() ); - CAPTURE( shooter.get_skill_level( shooter.get_wielded_item()->gun_skill() ) ); + CAPTURE( shooter.get_wielded_item().gun_skill().str() ); + CAPTURE( shooter.get_skill_level( shooter.get_wielded_item().gun_skill() ) ); CAPTURE( shooter.get_dex() ); - CAPTURE( to_milliliter( shooter.get_wielded_item()->volume() ) ); + CAPTURE( to_milliliter( shooter.get_wielded_item().volume() ) ); CAPTURE( fast_stats.n() ); CAPTURE( fast_stats.margin_of_error() ); CHECK( fast_stats.avg() > hit_rate ); diff --git a/tests/reloading_test.cpp b/tests/reloading_test.cpp index bc6994b847b89..5a84cc5244cfb 100644 --- a/tests/reloading_test.cpp +++ b/tests/reloading_test.cpp @@ -137,19 +137,19 @@ static void reload_a_revolver( Character &dummy, item &gun, item &ammo ) if( !dummy.is_wielding( gun ) ) { if( dummy.has_weapon() ) { // to avoid dispose_option in player::unwield() - dummy.i_add( *dummy.get_wielded_item() ); + dummy.i_add( dummy.get_wielded_item() ); dummy.remove_weapon(); } dummy.wield( gun ); } - while( dummy.get_wielded_item()->remaining_ammo_capacity() > 0 ) { + while( dummy.get_wielded_item().remaining_ammo_capacity() > 0 ) { g->reload_weapon( false ); REQUIRE( dummy.activity ); process_activity( dummy ); - CAPTURE( dummy.get_wielded_item()->typeId() ); + CAPTURE( dummy.get_wielded_item().typeId() ); CAPTURE( ammo.typeId() ); - CHECK( !dummy.get_wielded_item()->empty() ); - CHECK( dummy.get_wielded_item()->ammo_current() == ammo.type->get_id() ); + CHECK( !dummy.get_wielded_item().empty() ); + CHECK( dummy.get_wielded_item().ammo_current() == ammo.type->get_id() ); } } @@ -176,11 +176,11 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) REQUIRE( ammo.is_ammo() ); dummy.set_wielded_item( item( "sw_610", calendar::turn_zero, 0 ) ); - REQUIRE( dummy.get_wielded_item()->ammo_remaining() == 0 ); - REQUIRE( dummy.get_wielded_item()->can_reload_with( ammo.type->get_id() ) ); + REQUIRE( dummy.get_wielded_item().ammo_remaining() == 0 ); + REQUIRE( dummy.get_wielded_item().can_reload_with( ammo.type->get_id() ) ); WHEN( "the player triggers auto reload until the revolver is full" ) { - reload_a_revolver( dummy, *dummy.get_wielded_item(), ammo ); + reload_a_revolver( dummy, dummy.get_wielded_item(), ammo ); WHEN( "the player triggers auto reload again" ) { g->reload_weapon( false ); THEN( "no activity is generated" ) { @@ -193,7 +193,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) REQUIRE( gun2.ammo_remaining() == 0 ); REQUIRE( gun2.can_reload_with( ammo.type->get_id() ) ); WHEN( "the player triggers auto reload until the first revolver is full" ) { - reload_a_revolver( dummy, *dummy.get_wielded_item(), ammo ); + reload_a_revolver( dummy, dummy.get_wielded_item(), ammo ); WHEN( "the player triggers auto reload until the second revolver is full" ) { reload_a_revolver( dummy, gun2, ammo ); WHEN( "the player triggers auto reload again" ) { @@ -221,7 +221,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) REQUIRE( mag.ammo_remaining() == 0 ); dummy.set_wielded_item( item( "glock_19", calendar::turn_zero, 0 ) ); - REQUIRE( dummy.get_wielded_item()->ammo_remaining() == 0 ); + REQUIRE( dummy.get_wielded_item().ammo_remaining() == 0 ); WHEN( "the player triggers auto reload" ) { g->reload_weapon( false ); @@ -242,7 +242,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) process_activity( dummy ); THEN( "The magazine is loaded into the gun" ) { - CHECK( dummy.get_wielded_item()->ammo_remaining() > 0 ); + CHECK( dummy.get_wielded_item().ammo_remaining() > 0 ); } WHEN( "the player triggers auto reload again" ) { g->reload_weapon( false ); @@ -278,7 +278,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) process_activity( dummy ); THEN( "The magazine is loaded into the gun" ) { - CHECK( dummy.get_wielded_item()->ammo_remaining() > 0 ); + CHECK( dummy.get_wielded_item().ammo_remaining() > 0 ); } WHEN( "the player triggers auto reload again" ) { g->reload_weapon( false ); @@ -326,42 +326,42 @@ TEST_CASE( "reload_liquid_container", "[reload],[liquid]" ) g->reload_wielded(); REQUIRE( dummy.activity ); process_activity( dummy ); - CHECK( dummy.get_wielded_item()->total_contained_volume() == ammo_volume ); + CHECK( dummy.get_wielded_item().total_contained_volume() == ammo_volume ); CHECK( ammo_jug.total_contained_volume() == units::volume() ); } SECTION( "reload liquid into partially filled container with same type liquid" ) { item water_one( "water_clean", calendar::turn_zero, 1 ); units::volume initial_volume = water_one.volume(); - dummy.get_wielded_item()->put_in( water_one, item_pocket::pocket_type::CONTAINER ); + dummy.get_wielded_item().put_in( water_one, item_pocket::pocket_type::CONTAINER ); g->reload_wielded(); REQUIRE( dummy.activity ); process_activity( dummy ); - CHECK( dummy.get_wielded_item()->total_contained_volume() == ammo_volume + initial_volume ); + CHECK( dummy.get_wielded_item().total_contained_volume() == ammo_volume + initial_volume ); CHECK( ammo_jug.total_contained_volume() == units::volume() ); } SECTION( "reload liquid into partially filled container with different type liquid" ) { item milk_one( "milk", calendar::turn_zero, 1 ); units::volume initial_volume = milk_one.volume(); - dummy.get_wielded_item()->put_in( milk_one, item_pocket::pocket_type::CONTAINER ); + dummy.get_wielded_item().put_in( milk_one, item_pocket::pocket_type::CONTAINER ); g->reload_wielded(); if( !!dummy.activity ) { process_activity( dummy ); } - CHECK( dummy.get_wielded_item()->total_contained_volume() == initial_volume ); + CHECK( dummy.get_wielded_item().total_contained_volume() == initial_volume ); CHECK( ammo_jug.total_contained_volume() == ammo_volume ); } SECTION( "reload liquid into container containing a non-liquid" ) { item pebble( "pebble", calendar::turn_zero, 1 ); units::volume initial_volume = pebble.volume(); - dummy.get_wielded_item()->put_in( pebble, item_pocket::pocket_type::CONTAINER ); + dummy.get_wielded_item().put_in( pebble, item_pocket::pocket_type::CONTAINER ); g->reload_wielded(); if( !!dummy.activity ) { process_activity( dummy ); } - CHECK( dummy.get_wielded_item()->total_contained_volume() == initial_volume ); + CHECK( dummy.get_wielded_item().total_contained_volume() == initial_volume ); CHECK( ammo_jug.total_contained_volume() == ammo_volume ); } @@ -371,10 +371,10 @@ TEST_CASE( "reload_liquid_container", "[reload],[liquid]" ) g->reload_wielded(); REQUIRE( dummy.activity ); process_activity( dummy ); - CHECK( dummy.get_wielded_item()->get_total_capacity() == - dummy.get_wielded_item()->total_contained_volume() ); + CHECK( dummy.get_wielded_item().get_total_capacity() == + dummy.get_wielded_item().total_contained_volume() ); CHECK( ammo_jug.total_contained_volume() + - dummy.get_wielded_item()->total_contained_volume() == ammo_volume ); + dummy.get_wielded_item().total_contained_volume() == ammo_volume ); } SECTION( "liquid reload from map" ) { @@ -390,7 +390,7 @@ TEST_CASE( "reload_liquid_container", "[reload],[liquid]" ) g->reload_wielded(); REQUIRE( dummy.activity ); process_activity( dummy ); - CHECK( dummy.get_wielded_item()->total_contained_volume() == ammo_volume ); + CHECK( dummy.get_wielded_item().total_contained_volume() == ammo_volume ); CHECK( ammo_jug.total_contained_volume() == units::volume() ); } @@ -401,7 +401,7 @@ TEST_CASE( "reload_liquid_container", "[reload],[liquid]" ) process_activity( dummy ); } CHECK( ammo_jug.total_contained_volume() == units::volume() ); - CHECK( dummy.get_wielded_item()->total_contained_volume() == units::volume() ); + CHECK( dummy.get_wielded_item().total_contained_volume() == units::volume() ); } } } diff --git a/tests/unload_naked_test.cpp b/tests/unload_naked_test.cpp index 4a7192e85830e..c9bcff23eed6e 100644 --- a/tests/unload_naked_test.cpp +++ b/tests/unload_naked_test.cpp @@ -34,16 +34,16 @@ TEST_CASE( "unload_revolver_naked_one_bullet", "[unload][nonmagzine]" ) REQUIRE( player_character.wield( revolver ) ); REQUIRE( player_character.is_armed( ) ); - CHECK( player_character.get_wielded_item()->ammo_remaining() == 1 ); + CHECK( player_character.get_wielded_item().ammo_remaining() == 1 ); // Unload weapon - item_location revo_loc( dummy, player_character.get_wielded_item() ); + item_location revo_loc( dummy, &player_character.get_wielded_item() ); player_character.moves = 100; REQUIRE( player_character.unload( revo_loc ) ); player_character.activity.do_turn( player_character ); // No bullets in wielded gun - CHECK( player_character.get_wielded_item()->ammo_remaining() == 0 ); + CHECK( player_character.get_wielded_item().ammo_remaining() == 0 ); // No bullets in inventory const std::vector bullets = dummy.items_with( []( const item & item ) { @@ -69,16 +69,16 @@ TEST_CASE( "unload_revolver_naked_fully_loaded", "[unload][nonmagzine]" ) REQUIRE( player_character.wield( revolver ) ); REQUIRE( player_character.is_armed( ) ); - CHECK( player_character.get_wielded_item()->remaining_ammo_capacity() == 0 ); + CHECK( player_character.get_wielded_item().remaining_ammo_capacity() == 0 ); // Unload weapon - item_location revo_loc( dummy, player_character.get_wielded_item() ); + item_location revo_loc( dummy, &player_character.get_wielded_item() ); player_character.moves = 100; REQUIRE( player_character.unload( revo_loc ) ); player_character.activity.do_turn( player_character ); // No bullets in wielded gun - CHECK( player_character.get_wielded_item()->ammo_remaining() == 0 ); + CHECK( player_character.get_wielded_item().ammo_remaining() == 0 ); // No bullets in inventory const std::vector bullets = dummy.items_with( []( const item & item ) { diff --git a/tests/unseal_and_spill_test.cpp b/tests/unseal_and_spill_test.cpp index 9cf9a489a8f40..92bc46242f749 100644 --- a/tests/unseal_and_spill_test.cpp +++ b/tests/unseal_and_spill_test.cpp @@ -423,7 +423,7 @@ void test_scenario::run() } case container_location::wielded: { REQUIRE( guy.wield( it ) ); - it_loc = item_location( guy, guy.get_wielded_item() ); + it_loc = item_location( guy, &guy.get_wielded_item() ); break; } case container_location::vehicle: { @@ -449,7 +449,7 @@ void test_scenario::run() return; } } - if( guy.get_wielded_item()->is_null() ) { + if( guy.get_wielded_item().is_null() ) { // so the guy does not wield spilled solid items item rag( test_rag ); REQUIRE( guy.wield( rag ) ); @@ -864,7 +864,7 @@ void test_scenario::run() match( guy, guy.worn, worn_results ); INFO( "checking wielded item" ); if( wielded_results ) { - match( item_location( guy, guy.get_wielded_item() ), *wielded_results ); + match( item_location( guy, &guy.get_wielded_item() ), *wielded_results ); } else { REQUIRE( !guy.is_armed() ); } diff --git a/tests/vehicle_part_test.cpp b/tests/vehicle_part_test.cpp index 017fc5b955614..b9ad5bfcee1ba 100644 --- a/tests/vehicle_part_test.cpp +++ b/tests/vehicle_part_test.cpp @@ -180,7 +180,7 @@ static void test_craft_via_rig( const std::vector &items, int give_battery character.activity.do_turn( character ); } - REQUIRE( character.get_wielded_item()->type->get_id() == recipe.result() ); + REQUIRE( character.get_wielded_item().type->get_id() == recipe.result() ); } else { REQUIRE_FALSE( can_craft ); } diff --git a/tests/vision_test.cpp b/tests/vision_test.cpp index f3bd679605ab2..5fbf4d40278a3 100644 --- a/tests/vision_test.cpp +++ b/tests/vision_test.cpp @@ -38,7 +38,6 @@ static std::string vision_test_info( map_test_case &t ) using namespace map_test_case_common; - out << "zlevels: " << here.has_zlevels() << '\n'; out << "origin: " << t.get_origin() << '\n'; out << "player: " << get_player_character().pos() << '\n'; out << "unimpaired_range: " << get_player_character().unimpaired_range() << '\n'; diff --git a/tests/visitable_remove_test.cpp b/tests/visitable_remove_test.cpp index 26c08edf630d0..3e72de9ba107c 100644 --- a/tests/visitable_remove_test.cpp +++ b/tests/visitable_remove_test.cpp @@ -147,7 +147,7 @@ TEST_CASE( "visitable_remove", "[visitable]" ) WHEN( "one of the bottles is wielded" ) { p.wield( p.worn.front().legacy_front() ); - REQUIRE( p.get_wielded_item()->typeId() == container_id ); + REQUIRE( p.get_wielded_item().typeId() == container_id ); REQUIRE( count_items( p, container_id ) == count ); REQUIRE( count_items( p, liquid_id ) == count ); @@ -163,7 +163,7 @@ TEST_CASE( "visitable_remove", "[visitable]" ) REQUIRE( count_items( p, liquid_id ) == 0 ); } THEN( "there is no currently wielded item" ) { - REQUIRE( p.get_wielded_item()->is_null() ); + REQUIRE( p.get_wielded_item().is_null() ); } THEN( "the correct number of items were removed" ) { REQUIRE( del.size() == count ); @@ -189,11 +189,11 @@ TEST_CASE( "visitable_remove", "[visitable]" ) THEN( "there is only one bottle remaining in the players possession" ) { REQUIRE( count_items( p, container_id ) == 1 ); AND_THEN( "the remaining bottle is currently wielded" ) { - REQUIRE( p.get_wielded_item()->typeId() == container_id ); + REQUIRE( p.get_wielded_item().typeId() == container_id ); AND_THEN( "the remaining water is contained by the currently wielded bottle" ) { - REQUIRE( p.get_wielded_item()->num_item_stacks() == 1 ); - REQUIRE( p.get_wielded_item()->has_item_with( has_liquid_filter ) ); + REQUIRE( p.get_wielded_item().num_item_stacks() == 1 ); + REQUIRE( p.get_wielded_item().has_item_with( has_liquid_filter ) ); } } } diff --git a/tests/wield_times_test.cpp b/tests/wield_times_test.cpp index 80bd685d3ef8c..a41c5420a7711 100644 --- a/tests/wield_times_test.cpp +++ b/tests/wield_times_test.cpp @@ -34,7 +34,7 @@ static void wield_check_from_inv( avatar &guy, const itype_id &item_name, const guy.set_moves( 1000 ); const int old_moves = guy.moves; REQUIRE( guy.wield( item_loc ) ); - CAPTURE( guy.get_wielded_item()->typeId() ); + CAPTURE( guy.get_wielded_item().typeId() ); int move_cost = old_moves - guy.moves; INFO( "Strength:" << guy.get_str() );