diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index 6694998e07cd3..447366dcf958c 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -197,5 +197,5 @@ jobs: if: failure() with: name: cata_test - path: tests/cata_test + path: tests/cata_test* if-no-files-found: ignore diff --git a/.github/workflows/msvc-full-features.yml b/.github/workflows/msvc-full-features.yml index 4612b31ae3079..bdc4df43511d5 100644 --- a/.github/workflows/msvc-full-features.yml +++ b/.github/workflows/msvc-full-features.yml @@ -59,7 +59,7 @@ jobs: id: runvcpkg with: additionalCachedPaths: '${{ runner.workspace }}/Cataclysm-DDA/msvc-full-features/vcpkg_installed' - appendedCacheKey: ${{ hashFiles( 'msvc-full-features/vcpkg.json', '.github/vcpkg_triplets/**' ) }} + appendedCacheKey: ${{ hashFiles( 'msvc-full-features/vcpkg.json', '.github/vcpkg_triplets/**' ) }}-x64 setupOnly: true vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' # We have to use at least this version of vcpkg to include fixes for yasm-tool's diff --git a/.github/workflows/object_creator.yml b/.github/workflows/object_creator.yml index 591ea498910dd..ef152275212fe 100644 --- a/.github/workflows/object_creator.yml +++ b/.github/workflows/object_creator.yml @@ -59,7 +59,7 @@ jobs: 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/**' ) }} + appendedCacheKey: ${{ hashFiles( '$msvc-full-features/vcpkg.json', 'msvc-object_creator/vcpkg.json', '.github/vcpkg_triplets/**' ) }}-x64 setupOnly: true vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' # We have to use at least this version of vcpkg to include fixes for yasm-tool's diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cfbb8a8bbbae3..63e5beb3a3eee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,6 +60,20 @@ jobs: fail-fast: false matrix: include: + - name: Windows Tiles x64 MSVC + artifact: windows-tiles-x64-msvc + arch: x64 + os: windows-2019 + mxe: none + ext: zip + content: application/zip + - name: Windows Tiles x32 MSVC + artifact: windows-tiles-x32-msvc + arch: x86 + os: windows-2019 + mxe: none + ext: zip + content: application/zip - name: Windows Tiles x64 mxe: x86_64 artifact: windows-tiles-x64 @@ -127,7 +141,28 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - - name: Install dependencies (windows) + - name: Install dependencies (windows msvc) (1/3) + if: runner.os == 'Windows' + uses: microsoft/setup-msbuild@v1.0.2 + - name: Install dependencies (windows msvc) (2/3) + if: runner.os == 'Windows' + 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/**' ) }}-${{ matrix.arch }} + 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: Install dependencies (windows msvc) (3/3) + if: runner.os == 'Windows' + run: | + vcpkg integrate install + - name: Install dependencies (windows mxe) if: matrix.mxe != 'none' run: | sudo apt install astyle autoconf automake autopoint bash bison bzip2 cmake flex gettext git g++ gperf intltool \ @@ -141,6 +176,9 @@ jobs: sudo add-apt-repository "deb [arch=amd64] https://pkg.mxe.cc/repos/apt `lsb_release -sc` main" sudo apt update sudo apt install mxe-{i686,x86-64}-w64-mingw32.static-{sdl2,sdl2-ttf,sdl2-image,sdl2-mixer,gettext} + curl -L -o libbacktrace-${{ matrix.mxe }}-w64-mingw32.tar.gz https://github.com/Qrox/libbacktrace/releases/download/2020-01-03/libbacktrace-${{ matrix.mxe }}-w64-mingw32.tar.gz + shasum -a 256 -c ./build-scripts/libbacktrace-${{ matrix.mxe }}-w64-mingw32-sha256 + sudo tar -xzf libbacktrace-${{ matrix.mxe }}-w64-mingw32.tar.gz --exclude=LICENSE -C /usr/lib/mxe/usr/${{ matrix.mxe }}-w64-mingw32.static - name: Install dependencies (Linux) if: runner.os == 'Linux' && matrix.mxe == 'none' && matrix.android == 'none' run: | @@ -152,8 +190,8 @@ jobs: run: | HOMEBREW_NO_AUTO_UPDATE=yes HOMEBREW_NO_INSTALL_CLEANUP=yes brew install sdl2 sdl2_image sdl2_ttf sdl2_mixer gettext ccache parallel pip3 install dmgbuild==1.4.2 biplist - - name: Build CDDA (linux) - if: runner.os == 'Linux' && matrix.mxe == 'none' && matrix.android == 'none' + - name: Create VERSION.TXT + shell: bash run: | cat >VERSION.txt <VERSION.txt <VERSION.txt <VERSION.txt <", "text": [ "The trains have long grown still, and your echoing footsteps are the only thing breaking the silence. For now.", - "The rails are slick here with a grey, quivering ooze welling up from below.", + "The rails are slick here with a gray, quivering ooze welling up from below.", "There is a low, droning hum emanating from the rail, making your teeth ache.", "The layer of dust is broken by a thick trail of stinking slime leading off into the darkness.", "The air stings like chlorine in some spots, around black splashes etched into the concrete.", @@ -68,7 +68,7 @@ "The tunnel's wall is covered in a thin membrane of shuddering flesh, growing (flowing? crawling?) from a broken pipe. You keep your distance.", "You notice a single line of three-fingered footprints, starting on the floor but continuing without pause on the walls before disappearing in a hole on the ceiling that's dripping sticky, bluish ichor.", "There is a shimmering spot above the rails. Looking through, you can see the night sky and hear something howl with hatred and hunger. You're certain it could not pass through an opening so small. You're also certain the gateway will grow.", - "The wall is carpeted by green-grey mushrooms, their caps turning towards you with anticipation.", + "The wall is carpeted by green-gray mushrooms, their caps turning towards you with anticipation.", "The wall's concrete is warped into a spiral relief, drawing your eye inexorably to its center. You force yourself to look away, and feel something shift behind the wall." ] } diff --git a/data/json/snippets/mutant_anatomy.json b/data/json/snippets/mutant_anatomy.json index ea89111284cb9..72a7ff3868fa3 100644 --- a/data/json/snippets/mutant_anatomy.json +++ b/data/json/snippets/mutant_anatomy.json @@ -163,7 +163,7 @@ "text": [ { "id": "cooked_mutant_lung_1", - "text": "A cooked piece of a mutant animal's lung. With a lot of work you can cut around the hardened shell of translucent gunk, but your only reward is getting to the spongy, grey, mostly-flavorless mass of tissue beneath." + "text": "A cooked piece of a mutant animal's lung. With a lot of work you can cut around the hardened shell of translucent gunk, but your only reward is getting to the spongy, gray, mostly-flavorless mass of tissue beneath." }, { "id": "cooked_mutant_lung_2", @@ -197,7 +197,7 @@ }, { "id": "mutant_liver_4", - "text": "A chunk of liver from a mutated animal. The surface is blackened and hard but cracked, exposing a few strips of fresh pink tissue underneath. After cracking the shell fully open, the inner tissue begins swelling at an alarming rate before turning grey and lifeless." + "text": "A chunk of liver from a mutated animal. The surface is blackened and hard but cracked, exposing a few strips of fresh pink tissue underneath. After cracking the shell fully open, the inner tissue begins swelling at an alarming rate before turning gray and lifeless." } ] }, @@ -211,7 +211,7 @@ }, { "id": "cooked_mutant_liver_2", - "text": "A cooked chunk of liver from a mutated animal. Instead of the matte grey-brown of a normal liver, this one turned disconcertingly orange after heating it up, and finger-sized flakes detach themselves from it at the slightest touch. The taste reminds you of slightly overripe avocado, but that's still better than you expected." + "text": "A cooked chunk of liver from a mutated animal. Instead of the matte gray-brown of a normal liver, this one turned disconcertingly orange after heating it up, and finger-sized flakes detach themselves from it at the slightest touch. The taste reminds you of slightly overripe avocado, but that's still better than you expected." }, { "id": "cooked_mutant_liver_3", @@ -219,7 +219,7 @@ }, { "id": "cooked_mutant_liver_4", - "text": "A cooked chunk of liver from a mutated animal. The tissue split apart following the veins before hardening, reminding you of a warped grey flower with a sinuous vein for a stem. Perhaps surprisingly, it tastes not entirely unlike liver." + "text": "A cooked chunk of liver from a mutated animal. The tissue split apart following the veins before hardening, reminding you of a warped gray flower with a sinuous vein for a stem. Perhaps surprisingly, it tastes not entirely unlike liver." } ] }, @@ -229,7 +229,7 @@ "text": [ { "id": "mutant_kidney_1", - "text": "A piece of kidney from a mutated animal. Cutting into it your knife slips, opening a large gash on its side from which tiny, beautiful pearls roll out. Before your eyes they start glistening with humidity and melt, leaving no trace beyond a stingin stench." + "text": "A piece of kidney from a mutated animal. While cutting into it your knife slips, opening a large gash on its side from which tiny, beautiful pearls roll out. Before your eyes they start glistening with humidity and melt, leaving no trace beyond a stinging stench." }, { "id": "mutant_kidney_2", @@ -285,7 +285,7 @@ }, { "id": "bug_organs_5", - "text": "This is a meaty grey organ you removed from a mutant. It has a chalky yellow coating that burns your skin, and several unidentifiable fleshy tubes sticking out of it. The smell it gives off stings your nostrils. You're pretty confident no natural creature has one of these." + "text": "This is a meaty gray organ you removed from a mutant. It has a chalky yellow coating that burns your skin, and several unidentifiable fleshy tubes sticking out of it. The smell it gives off stings your nostrils. You're pretty confident no natural creature has one of these." }, { "id": "bug_organs_6", @@ -355,7 +355,7 @@ "type": "snippet", "category": "", "text": [ - "Spaced evenly across the entire body you find small sacs of eggs in different stages of growth", + "Spaced evenly across the entire body you find small sacs of eggs in various stages of growth", "Its intestines grew into a labyrinthine tangle, like so many worms devouring each other", "Inside, half-formed organs press against spongy meat that doesn't look anything like raw arthropod meat from normal creatures", "Beneath, you find a collection of hooked spines that seem to have been clasping it on somehow", @@ -486,9 +486,9 @@ "", "", "The chaotic bundle of organs in its torso look much like those of other mutated insects, but as you near the abdomen there's order to the madness: comparatively neat rows of venom-filled glands, each feeding into a reservoir at the base of the stinger", - "You open a stomach, releasing a gush of sweet-smelling grey fluid", + "You open a stomach, releasing a gush of sweet-smelling gray fluid", "For its apparent hunger for meat, its intestines seem almost atrophied", - "Your knife reaches the retracted stinger and slips on its smooth surface, opening half a dozen venom glands in the process. You haven't cut yourself, have you?", + "Your knife reaches the retracted stinger and slips on its smooth surface, opening half a dozen venom glands in the process. You dearly hope that you have not cut yourself", "You find a handful of dead grubs underneath its chitin, near a chewed-open venom gland" ] }, @@ -508,7 +508,6 @@ "text": [ "", "Steaming puddles of acid spill from its outer shell as you pull it back", - "With the creature dead, its carapace comes away surprisingly easily", "Steaming acid burbles from the creature's chitin as you peel it back", "Several acid glands rupture as you peel back the carapace, sending streams of steaming caustic fluids spraying around" ] diff --git a/data/json/snippets/snippets.json b/data/json/snippets/snippets.json index a5cb4594c7756..4508e41a6fe36 100644 --- a/data/json/snippets/snippets.json +++ b/data/json/snippets/snippets.json @@ -213,6 +213,52 @@ "category": "dogwhistle_message_you", "text": [ "You hate this loud sound." ] }, + { + "type": "snippet", + "category": "examine_photo_msg", + "text": [ + "You used to have a dog like this…", + "Ha-ha! An amusing cat photo.", + "Excellent pictures of nature.", + "Food photos… your stomach rumbles!", + "Some very interesting travel photos.", + "Pictures of a concert of popular band.", + "Photos of someone's luxurious house.", + "You feel nostalgic as you stare at the photo." + ] + }, + { + "type": "snippet", + "category": "magic_8ball_good", + "text": [ + "It is certain.", + "It is decidedly so.", + "Without a doubt.", + "Yes - definitely.", + "You may rely on it.", + "As I see it, yes.", + "Most likely.", + "Outlook good.", + "Yes.", + "Signs point to yes." + ] + }, + { + "type": "snippet", + "category": "magic_8ball_unknown", + "text": [ + "Reply hazy, try again.", + "Ask again later.", + "Better not tell you now.", + "Can't predict now.", + "Concentrate and ask again." + ] + }, + { + "type": "snippet", + "category": "magic_8ball_bad", + "text": [ "Don't count on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful." ] + }, { "type": "snippet", "category": "slime_cheers", diff --git a/data/mods/CRT_EXPANSION/items/crt_toolarmor.json b/data/mods/CRT_EXPANSION/items/crt_toolarmor.json index 66c2683732ec8..6adc03c5070a3 100644 --- a/data/mods/CRT_EXPANSION/items/crt_toolarmor.json +++ b/data/mods/CRT_EXPANSION/items/crt_toolarmor.json @@ -9,8 +9,6 @@ "volume": "1 L", "price": 2500000, "to_hit": 1, - "max_charges": 250, - "initial_charges": 250, "use_action": { "type": "transform", "msg": "CRIT HUD booting up…", @@ -26,6 +24,7 @@ "material_thickness": 5, "environmental_protection": 16, "qualities": [ [ "GLARE", 1 ] ], + "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "battery": 250 } } ], "flags": [ "WATERPROOF", "STURDY", @@ -35,22 +34,18 @@ "GAS_PROOF", "USE_UPS", "NO_UNLOAD", + "NO_RELOAD", "SLEEP_IGNORE" ], "armor": [ { "encumbrance": 50, "coverage": 100, "covers": [ "eyes", "mouth" ] } ] }, { "id": "crt_gasmask_on", + "copy-from": "crt_gasmask", "type": "TOOL_ARMOR", - "category": "armor", "name": { "str": "CRIT gas mask (on)", "str_pl": "CRIT gas masks (on)" }, "description": "This a heavily modified gas mask. It is currently on and draining power for the HUD, low-level night vision and other protective elements.", - "weight": "5 kg", - "volume": "1 L", - "price": 2500000, "to_hit": -3, - "max_charges": 250, - "initial_charges": 250, "turns_per_charge": 1, "revert_to": "crt_gasmask", "use_action": { "type": "transform", "menu_text": "Turn off", "msg": "CRIT HUD deactivating.", "target": "crt_gasmask" }, @@ -75,6 +70,7 @@ "GAS_PROOF", "USE_UPS", "NO_UNLOAD", + "NO_RELOAD", "SLEEP_IGNORE" ], "armor": [ { "encumbrance": 5, "coverage": 100, "covers": [ "eyes", "mouth" ] } ] @@ -93,8 +89,6 @@ "material": [ "kevlar", "superalloy" ], "symbol": "[", "color": "light_gray", - "max_charges": 300, - "initial_charges": 300, "charges_per_use": 1, "use_action": { "type": "transform", @@ -106,38 +100,26 @@ }, "//": "Artifact data is charge_type solar", "pocket_data": [ + { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "battery": 300 } }, { "pocket_type": "CONTAINER", "max_contains_volume": "2 L", "max_contains_weight": "6 kg", "moves": 80 }, { "pocket_type": "CONTAINER", "max_contains_volume": "2 L", "max_contains_weight": "6 kg", "moves": 80 } ], "warmth": 10, "material_thickness": 4, "environmental_protection": 4, - "flags": [ "WATER_FRIENDLY", "STURDY", "VARSIZE", "USE_UPS", "NO_UNLOAD", "OUTER" ], + "flags": [ "WATER_FRIENDLY", "STURDY", "VARSIZE", "USE_UPS", "NO_UNLOAD", "NO_RELOAD", "OUTER" ], "armor": [ { "encumbrance": 50, "coverage": 85, "covers": [ "torso" ] } ] }, { "id": "crt_em_vest_on", + "copy-from": "crt_em_vest", "type": "TOOL_ARMOR", - "category": "armor", "name": { "str": "CRIT EM vest (on)", "str_pl": "CRIT EM vests (on)" }, "description": "The Spec Ops Enhanced Movement vest is embedded with high-tech filaments, reactive servos and a generator which pumps a crystallized liquid that protects its wearer from most heavy combat situations at the cost of extreme power usage. It is commonly worn by C.R.I.T Spec Ops. This vest is currently in suit form and draining your UPS power at high rates.", - "weight": "10 kg", - "volume": "6250 ml", - "price": 7000000, - "to_hit": -3, - "bashing": 6, - "material": [ "kevlar", "superalloy" ], - "symbol": "[", "color": "light_green", - "pocket_data": [ - { "pocket_type": "CONTAINER", "max_contains_volume": "2 L", "max_contains_weight": "6 kg", "moves": 40 }, - { "pocket_type": "CONTAINER", "max_contains_volume": "2 L", "max_contains_weight": "6 kg", "moves": 40 } - ], "warmth": 100, "material_thickness": 7, "environmental_protection": 16, - "max_charges": 300, - "initial_charges": 300, "turns_per_charge": 1, "charges_per_use": 1, "revert_to": "crt_em_vest", @@ -161,6 +143,7 @@ "TRADER_AVOID", "USE_UPS", "NO_UNLOAD", + "NO_RELOAD", "OUTER" ], "armor": [ { "encumbrance": 5, "coverage": 100, "covers": [ "torso", "leg_l", "leg_r", "arm_l", "arm_r" ] } ] @@ -175,7 +158,6 @@ "material": [ "kevlar", "hardsteel" ], "material_thickness": 3, "warmth": 20, - "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "battery": 100 } } ], "charges_per_use": 1, "ammo": "battery", "use_action": { @@ -186,7 +168,19 @@ "need_charges": 1, "need_charges_msg": "The helmet's batteries are dead." }, - "flags": [ "WATERPROOF", "STURDY", "VARSIZE", "RAD_PROOF", "kevlar_padded", "TRADER_AVOID", "USE_UPS", "NO_UNLOAD", "OUTER" ] + "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "battery": 100 } } ], + "flags": [ + "WATERPROOF", + "STURDY", + "VARSIZE", + "RAD_PROOF", + "kevlar_padded", + "TRADER_AVOID", + "USE_UPS", + "NO_RELOAD", + "NO_UNLOAD", + "OUTER" + ] }, { "id": "crt_helmet_on", @@ -202,6 +196,7 @@ "VARSIZE", "kevlar_padded", "USE_UPS", + "NO_RELOAD", "NO_UNLOAD", "OUTER", "LIGHT_35", diff --git a/data/mods/CRT_EXPANSION/items/crt_tools.json b/data/mods/CRT_EXPANSION/items/crt_tools.json index 487836230e714..b654145c89c61 100644 --- a/data/mods/CRT_EXPANSION/items/crt_tools.json +++ b/data/mods/CRT_EXPANSION/items/crt_tools.json @@ -14,10 +14,17 @@ "color": "green", "ammo": [ "battery" ], "sub": "hotplate", - "pocket_data": [ { "pocket_type": "MAGAZINE", "rigid": true, "ammo_restriction": { "battery": 75 } } ], "charges_per_use": 1, "qualities": [ [ "COOK", 2 ], [ "BOIL", 2 ], [ "CONTAIN", 1 ] ], "//": "Legacy artifact data is set charge solar", + "pocket_data": [ + { + "pocket_type": "MAGAZINE_WELL", + "rigid": true, + "flag_restriction": [ "BATTERY_ULTRA_LIGHT" ], + "default_magazine": "light_minus_battery_cell" + } + ], "use_action": [ "HOTPLATE" ] }, { diff --git a/data/mods/sees_player_retro/mod_tileset.json b/data/mods/sees_player_retro/mod_tileset.json index 552057309e069..3ba0bb642d601 100644 --- a/data/mods/sees_player_retro/mod_tileset.json +++ b/data/mods/sees_player_retro/mod_tileset.json @@ -3,17 +3,35 @@ "type": "mod_tileset", "compatibility": [ "retrodays", "neodays" ], "tiles-new": [ + { + "file": "sees_player_retro.png", + "sprite_width": 10, + "sprite_height": 10, + "sprite_offset_x": 0, + "sprite_offset_y": -5, + "tiles": [ + { "id": "overlay_run", "bg": 1 }, + { "id": "overlay_crouch", "bg": 2 }, + { "id": "overlay_effect_bleed", "bg": 3 }, + { "id": "overlay_prone", "bg": 4 } + ] + }, { "file": "sees_player_retro.png", "tiles": [ { "id": "overlay_hostile_sees_player", "fg": 0 }, { "id": "overlay_friendly_sees_player", "fg": 0 }, { "id": "overlay_neutral_sees_player", "fg": 0 }, - { "id": "overlay_other_sees_player", "fg": 0 }, - { "id": "overlay_run", "fg": 1 }, - { "id": "overlay_crouch", "fg": 2 }, - { "id": "overlay_effect_bleed", "fg": 3 } + { "id": "overlay_other_sees_player", "fg": 0 } ] + }, + { + "file": "sees_player_retro.png", + "sprite_width": 10, + "sprite_height": 10, + "sprite_offset_x": 0, + "sprite_offset_y": -1, + "tiles": [ { "id": "overlay_effect_haslight", "fg": 5 } ] } ] } diff --git a/data/mods/sees_player_retro/modinfo.json b/data/mods/sees_player_retro/modinfo.json index db719c1b01c9d..b416d2de200d6 100644 --- a/data/mods/sees_player_retro/modinfo.json +++ b/data/mods/sees_player_retro/modinfo.json @@ -3,8 +3,8 @@ "type": "MOD_INFO", "id": "sees_player_retro", "name": "sees-player, run, crouch, bleed icons, retrodays", - "authors": [ "esotericist" ], - "description": "Adds indicator icon if a creature sees the player. Adds status icons for run, crouch, bleeding on top of player tile. Designed for the retrodays tileset.", + "authors": [ "esotericist", "dranitski" ], + "description": "Adds indicator icon if a creature sees the player. Adds status icons for run, crouch, prone, bleeding, light on top of player tile. Designed for the retrodays tileset, but works fine with neodays too.", "category": "graphical", "dependencies": [ "dda" ] } diff --git a/data/mods/sees_player_retro/sees_player_retro.png b/data/mods/sees_player_retro/sees_player_retro.png index 82ddae276080b..b96def33b6ecf 100644 Binary files a/data/mods/sees_player_retro/sees_player_retro.png and b/data/mods/sees_player_retro/sees_player_retro.png differ diff --git a/doc/COMPILING/COMPILING.md b/doc/COMPILING/COMPILING.md index e5c2cdc17634f..01a8ee024796a 100644 --- a/doc/COMPILING/COMPILING.md +++ b/doc/COMPILING/COMPILING.md @@ -212,7 +212,7 @@ Installation cd ~/src git clone https://github.com/CleverRaven/Cataclysm-DDA.git ./Cataclysm-DDA git clone https://github.com/mxe/mxe.git ./mxe - make -j$((`nproc`+0)) MXE_TARGETS='x86_64-w64-mingw32.static i686-w64-mingw32.static' sdl2 sdl2_ttf sdl2_image sdl2_mixer gettext + make -j$((`nproc`+0)) MXE_TARGETS='x86_64-w64-mingw32.static i686-w64-mingw32.static' MXE_PLUGIN_DIRS=plugins/gcc9 sdl2 sdl2_ttf sdl2_image sdl2_mixer gettext Building all these packages from MXE might take a while, even on a fast computer. Be patient; the `-j` flag will take advantage of all your processor cores. If you are not planning on building for both 32-bit and 64-bit, you might want to adjust your MXE_TARGETS. diff --git a/doc/EXAMINE.md b/doc/EXAMINE.md index 5d127183006f1..fc5b12e27ce53 100644 --- a/doc/EXAMINE.md +++ b/doc/EXAMINE.md @@ -16,7 +16,6 @@ The examine actors are specified as JSON objects with a `type` corresponding to - ```controls_gate``` Controls the attached gate. - ```dirtmound``` Plant seeds and plants. - ```elevator``` Use the elevator to change floors. -- ```fault``` Displays descriptive message, but otherwise unused. - ```flower_poppy``` Pick the mutated poppy. - ```fswitch``` Flip the switch and the rocks will shift. - ```fungus``` Release spores as the terrain crumbles away. @@ -132,3 +131,9 @@ What message to print when attempting to activate the cardreader after it has al "redundant_msg": "The door is already open." } ``` +### `effect_on_condition` + +#### `effect_on_conditions` +Mandatory. +Array of strings and or effect_on_condition objects. +Run all of the eocs upon being examined with u as the examiner and npc as null. See [EFFECT_ON_CONDITION.md](EFFECT_ON_CONDITION.md) diff --git a/doc/NPCs.md b/doc/NPCs.md index 1e0eb579ffdcd..ff17b5b284605 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -715,7 +715,11 @@ Condition | Type | Description the value of `u_has_focus` or `npc_has_focus` ( or the value of the variable described see `variable_object` above). `"u_is_on_terrain"`
`"npc_is_on_terrain"` | string | `true` if the player character or NPC is on terrain named `"u_is_on_terrain"` or `"npc_is_on_terrain"`. `"u_is_in_field"`
`"npc_is_in_field"` | string | `true` if the player character or NPC is in a field of type `"u_is_in_field"` or `"npc_is_in_field"`.. - +`"u_query"`
`"npc_query", default : bool` | string | if the player character or NPC is the avatar will popup a yes/no query with the provided message and users response is used as the return value. If called for a non avatar will return `default`. +example +``` +"condition": { "u_query": "Should we test?", "default": true }, +``` #### Player Only conditions `"u_has_mission"` | string | `true` if the mission is assigned to the player character. diff --git a/lang/compile_mo.sh b/lang/compile_mo.sh index 290bbb1a901f7..9b25ac509d3af 100755 --- a/lang/compile_mo.sh +++ b/lang/compile_mo.sh @@ -1,5 +1,7 @@ #!/bin/sh +set -x + if [ ! -d lang/po ] then if [ -d ../lang/po ] diff --git a/lang/extract_json_strings.py b/lang/extract_json_strings.py index 8ea8f82f4db27..df2ce4b847f0e 100755 --- a/lang/extract_json_strings.py +++ b/lang/extract_json_strings.py @@ -222,6 +222,21 @@ def warning_supressed(filename): def gender_options(subject): return [subject + ":" + g for g in all_genders] + +def get_singular_name(name): + if type(name) is dict: + if "str_sp" in name: + return name["str_sp"] + elif "str" in name: + return name["str"] + else: + raise Exception("Cannot find singular name in {}".format(name)) + elif type(name) is str: + return name + else: + raise Exception("Cannot find singular name in {}".format(name)) + + # # SPECIALIZED EXTRACTION FUNCTIONS # @@ -797,8 +812,9 @@ def extract_missiondef(item): if item_name is None: raise WrongJSONItem("JSON item don't contain 'name' field", item) writestr(outfile, item_name) + singular_name = get_singular_name(item_name) if "description" in item: - comment = "Description for mission '{}'".format(item_name) + comment = "Description for mission '{}'".format(singular_name) writestr(outfile, item["description"], comment=comment) if "dialogue" in item: dialogue = item.get("dialogue") @@ -1304,10 +1320,7 @@ def extract(item, infilename): else: writestr(outfile, name, **kwargs) wrote = True - if type(name) is dict and "str" in name: - singular_name = name["str"] - else: - singular_name = name + singular_name = get_singular_name(name) def do_extract(item): wrote = False @@ -1327,7 +1340,7 @@ def do_extract(item): if "conditional_names" in item: for cname in item["conditional_names"]: c = "Conditional name for {} when {} matches {}".format( - name, cname["type"], cname["condition"]) + singular_name, cname["type"], cname["condition"]) writestr(outfile, cname["name"], comment=c, format_strings=True, pl_fmt=True, **kwargs) wrote = True diff --git a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj index 36ba9f2fd8884..d45b4f151f1d7 100644 --- a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj @@ -92,7 +92,6 @@ MaxSpeed true true - NDEBUG;%(PreprocessorDefinitions) DebugFastLink MultiThreaded diff --git a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj index 59c79d81a2841..134800ec6682f 100644 --- a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj @@ -92,7 +92,6 @@ MaxSpeed true true - NDEBUG;%(PreprocessorDefinitions) DebugFastLink MultiThreaded diff --git a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj index f98e74873964e..a82a90bf9117e 100644 --- a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj @@ -70,6 +70,22 @@ false + + false + cataclysm-tiles + + + false + cataclysm-tiles + + + false + cataclysm-tiles + + + false + cataclysm-tiles + _WINDOWS;USE_WINMAIN;TILES;%(PreprocessorDefinitions) @@ -91,7 +107,6 @@ MaxSpeed true true - NDEBUG;%(PreprocessorDefinitions) DebugFastLink MultiThreaded @@ -117,6 +132,9 @@ {0009bb11-11ad-4c14-a5fc-d882a942c00b} + + + diff --git a/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj b/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj index be41ffcb476a1..2b465ff42a4e0 100644 --- a/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj +++ b/msvc-full-features/JsonFormatter-lib-vcpkg-static.vcxproj @@ -94,7 +94,6 @@ MaxSpeed true true - NDEBUG;%(PreprocessorDefinitions) DebugFastLink MultiThreaded diff --git a/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj b/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj index 701cb1c8650c1..7301034e73f40 100644 --- a/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj +++ b/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj @@ -71,6 +71,18 @@ false + + json_formatter + + + json_formatter + + + json_formatter + + + json_formatter + _CONSOLE;%(PreprocessorDefinitions) @@ -92,7 +104,6 @@ MaxSpeed true true - NDEBUG;%(PreprocessorDefinitions) DebugFastLink MultiThreaded diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp index bf47843ee5ca5..1cf39b68f62d4 100644 --- a/src/activity_item_handling.cpp +++ b/src/activity_item_handling.cpp @@ -1444,8 +1444,16 @@ static void add_basecamp_storage_to_loot_zone_list( zone_manager &mgr, const tri std::unordered_set bc_storage_set = mgr.get_near( zone_type_id( "CAMP_STORAGE" ), here.getabs( src_loc ), ACTIVITY_SEARCH_DISTANCE ); for( const tripoint &elem : bc_storage_set ) { - loot_zone_spots.push_back( here.getlocal( elem ) ); - combined_spots.push_back( here.getlocal( elem ) ); + tripoint here_local = here.getlocal( elem ); + + // Check that a coordinate is not already in the combined list, otherwise actions + // like construction may erroneously count materials twice if an object is both + // in the camp zone and in a loot zone. + if( std::find( combined_spots.begin(), combined_spots.end(), + here_local ) == combined_spots.end() ) { + loot_zone_spots.push_back( here_local ); + combined_spots.push_back( here_local ); + } } } } diff --git a/src/condition.cpp b/src/condition.cpp index be37585729c4f..a877423744ed4 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -828,6 +828,22 @@ void conditional_t::set_one_in_chance( const JsonObject &jo, const std::strin }; } +template +void conditional_t::set_query( const JsonObject &jo, const std::string &member, bool is_npc ) +{ + std::string message = jo.get_string( member ); + bool default_val = jo.get_bool( "default" ); + condition = [message, default_val, is_npc]( const T & d ) { + const talker *actor = d.actor( is_npc ); + if( actor->get_character() && actor->get_character()->is_avatar() ) { + std::string translated_message = _( message ); + return query_yn( translated_message ); + } else { + return default_val; + } + }; +} + template void conditional_t::set_x_in_y_chance( const JsonObject &jo, const std::string &member ) { @@ -1467,6 +1483,10 @@ conditional_t::conditional_t( const JsonObject &jo ) set_need( jo, "u_need" ); } else if( jo.has_string( "npc_need" ) ) { set_need( jo, "npc_need", is_npc ); + } else if( jo.has_member( "u_query" ) ) { + set_query( jo, "u_query" ); + } else if( jo.has_member( "npc_query" ) ) { + set_query( jo, "npc_query", is_npc ); } else if( jo.has_string( "u_at_om_location" ) ) { set_at_om_location( jo, "u_at_om_location" ); } else if( jo.has_string( "npc_at_om_location" ) ) { diff --git a/src/condition.h b/src/condition.h index a47f68ea075d6..dca0fc6f6a8b5 100644 --- a/src/condition.h +++ b/src/condition.h @@ -38,7 +38,7 @@ const std::unordered_set complex_conds = { { "u_has_items", "npc_has_items", "u_has_item_category", "npc_has_item_category", "u_has_bionics", "npc_has_bionics", "u_has_effect", "npc_has_effect", "u_need", "npc_need", "u_at_om_location", "npc_at_om_location", "npc_role_nearby", "npc_allies", "npc_service", - "u_has_cash", "u_are_owed", + "u_has_cash", "u_are_owed", "u_query", "npc_query", "npc_aim_rule", "npc_engagement_rule", "npc_rule", "npc_override", "npc_cbm_reserve_rule", "npc_cbm_recharge_rule", "days_since_cataclysm", "is_season", "mission_goal", "u_has_var", "npc_has_var", @@ -155,6 +155,7 @@ struct conditional_t { void set_is_on_terrain( const JsonObject &jo, const std::string &member, bool is_npc = false ); void set_is_in_field( const JsonObject &jo, const std::string &member, bool is_npc = false ); void set_one_in_chance( const JsonObject &jo, const std::string &member ); + void set_query( const JsonObject &jo, const std::string &member, bool is_npc = false ); void set_x_in_y_chance( const JsonObject &jo, const std::string &member ); void set_has_worn_with_flag( const JsonObject &jo, const std::string &member, bool is_npc = false ); void set_has_wielded_with_flag( const JsonObject &jo, const std::string &member, diff --git a/src/effect_on_condition.cpp b/src/effect_on_condition.cpp index c0d928e8c11c6..a0f59a7fa3710 100644 --- a/src/effect_on_condition.cpp +++ b/src/effect_on_condition.cpp @@ -122,7 +122,7 @@ void effect_on_conditions::load_new_character( Character &you ) for( const effect_on_condition_id &eoc_id : get_scenario()->eoc() ) { effect_on_condition eoc = eoc_id.obj(); if( eoc.type == eoc_type::SCENARIO_SPECIFIC && ( is_avatar || eoc.run_for_npcs ) ) { - queued_eoc new_eoc = queued_eoc{ eoc.id, true, calendar::turn + next_recurrence( eoc.id ) }; + queued_eoc new_eoc = queued_eoc{ eoc.id, true, calendar::turn_zero }; you.queued_effect_on_conditions.push( new_eoc ); } } diff --git a/src/iexamine.cpp b/src/iexamine.cpp index c40b18fa13d6d..89c817cf52ec6 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -1682,16 +1682,6 @@ void iexamine::bulletin_board( Character &you, const tripoint &examp ) } } -/** - * Display popup with reference to "The Enigma of Amigara Fault." - */ -void iexamine::fault( Character &, const tripoint & ) -{ - popup( _( "This wall is perfectly vertical. Odd, twisted holes are set in it, leading\n" - "as far back into the solid rock as you can see. The holes are humanoid in\n" - "shape, but with long, twisted, distended limbs." ) ); -} - /** * Spawn 1d4 wyrms and sink pedestal into ground. */ @@ -6257,7 +6247,6 @@ iexamine_functions iexamine_functions_from_string( const std::string &function_n { "slot_machine", &iexamine::slot_machine }, { "safe", &iexamine::safe }, { "bulletin_board", &iexamine::bulletin_board }, - { "fault", &iexamine::fault }, { "pedestal_wyrm", &iexamine::pedestal_wyrm }, { "pedestal_temple", &iexamine::pedestal_temple }, { "door_peephole", &iexamine::door_peephole }, diff --git a/src/iexamine.h b/src/iexamine.h index ff1b061c19e48..71c9088b009dd 100644 --- a/src/iexamine.h +++ b/src/iexamine.h @@ -81,7 +81,6 @@ void harvested_plant( Character &you, const tripoint &examp ); void locked_object( Character &you, const tripoint &examp ); void locked_object_pickable( Character &you, const tripoint &examp ); void bulletin_board( Character &you, const tripoint &examp ); -void fault( Character &you, const tripoint &examp ); void pedestal_wyrm( Character &you, const tripoint &examp ); void pedestal_temple( Character &you, const tripoint &examp ); void door_peephole( Character &you, const tripoint &examp ); diff --git a/src/iexamine_actors.cpp b/src/iexamine_actors.cpp index d5b906712dac2..d87fdced9a6fe 100644 --- a/src/iexamine_actors.cpp +++ b/src/iexamine_actors.cpp @@ -1,5 +1,7 @@ #include "iexamine_actors.h" +#include "avatar.h" +#include "effect_on_condition.h" #include "game.h" #include "generic_factory.h" #include "itype.h" @@ -192,3 +194,32 @@ std::unique_ptr cardreader_examine_actor::clone() const { return std::make_unique( *this ); } + +void eoc_examine_actor::call( Character &you, const tripoint & ) const +{ + dialogue d( get_talker_for( you ), nullptr ); + for( const effect_on_condition_id &eoc : eocs ) { + eoc->activate( d ); + } +} + +void eoc_examine_actor::load( const JsonObject &jo ) +{ + for( JsonValue jv : jo.get_array( "effect_on_conditions" ) ) { + eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + } +} + +void eoc_examine_actor::finalize() const +{ + for( const effect_on_condition_id &eoc : eocs ) { + if( !eoc.is_valid() ) { + debugmsg( "Invalid effect_on_condition_id: %s", eoc.str() ); + } + } +} + +std::unique_ptr eoc_examine_actor::clone() const +{ + return std::make_unique( *this ); +} diff --git a/src/iexamine_actors.h b/src/iexamine_actors.h index f98d31800ff4b..b6b7708b273bc 100644 --- a/src/iexamine_actors.h +++ b/src/iexamine_actors.h @@ -49,4 +49,18 @@ class cardreader_examine_actor : public iexamine_actor std::unique_ptr clone() const override; }; +class eoc_examine_actor : public iexamine_actor +{ + private: + std::vector eocs; + public: + explicit eoc_examine_actor( const std::string &type = "effect_on_condition" ) + : iexamine_actor( type ) {} + + void load( const JsonObject &jo ) override; + void call( Character &you, const tripoint &examp ) const override; + void finalize() const override; + + std::unique_ptr clone() const override; +}; #endif // CATA_SRC_IEXAMINE_ACTORS_H diff --git a/src/iuse.cpp b/src/iuse.cpp index 4c557a9df08e6..6b300b300c25d 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -6126,34 +6126,8 @@ cata::optional iuse::einktabletpc( Character *p, item *it, bool t, const tr p->add_msg_if_player( m_info, _( "Wasted time. These pictures do not provoke your senses." ) ); } else { p->add_morale( MORALE_PHOTOS, rng( 15, 30 ), 100 ); - - const int random_photo = rng( 1, 20 ); - switch( random_photo ) { - case 1: - p->add_msg_if_player( m_good, _( "You used to have a dog like this…" ) ); - break; - case 2: - p->add_msg_if_player( m_good, _( "Ha-ha! An amusing cat photo." ) ); - break; - case 3: - p->add_msg_if_player( m_good, _( "Excellent pictures of nature." ) ); - break; - case 4: - p->add_msg_if_player( m_good, _( "Food photos… your stomach rumbles!" ) ); - break; - case 5: - p->add_msg_if_player( m_good, _( "Some very interesting travel photos." ) ); - break; - case 6: - p->add_msg_if_player( m_good, _( "Pictures of a concert of popular band." ) ); - break; - case 7: - p->add_msg_if_player( m_good, _( "Photos of someone's luxurious house." ) ); - break; - default: - p->add_msg_if_player( m_good, _( "You feel nostalgic as you stare at the photo." ) ); - break; - } + p->add_msg_if_player( m_good, "%s", + SNIPPET.random_from_category( "examine_photo_msg" ).value_or( translation() ) ); } return it->type->charges_to_use(); @@ -9519,39 +9493,22 @@ cata::optional iuse::play_game( Character *p, item *it, bool, const tripoin cata::optional iuse::magic_8_ball( Character *p, item *it, bool, const tripoint & ) { - enum { - BALL8_GOOD, - BALL8_UNK = 10, - BALL8_BAD = 15 - }; - static const std::array tab = {{ - translate_marker( "It is certain." ), - translate_marker( "It is decidedly so." ), - translate_marker( "Without a doubt." ), - translate_marker( "Yes - definitely." ), - translate_marker( "You may rely on it." ), - translate_marker( "As I see it, yes." ), - translate_marker( "Most likely." ), - translate_marker( "Outlook good." ), - translate_marker( "Yes." ), - translate_marker( "Signs point to yes." ), - translate_marker( "Reply hazy, try again." ), - translate_marker( "Ask again later." ), - translate_marker( "Better not tell you now." ), - translate_marker( "Can't predict now." ), - translate_marker( "Concentrate and ask again." ), - translate_marker( "Don't count on it." ), - translate_marker( "My reply is no." ), - translate_marker( "My sources say no." ), - translate_marker( "Outlook not so good." ), - translate_marker( "Very doubtful." ) - } - }; - p->add_msg_if_player( m_info, _( "You ask the %s, then flip it." ), it->tname() ); - int rn = rng( 0, tab.size() - 1 ); - game_message_type color = ( rn >= BALL8_BAD ? m_bad : rn >= BALL8_UNK ? m_info : m_good ); - p->add_msg_if_player( color, _( "The %s says: %s" ), it->tname(), _( tab[rn] ) ); + int rn = rng( 0, 3 ); + std::string msg_category; + game_message_type color; + if( rn == 0 ) { + msg_category = "magic_8ball_bad"; + color = m_bad; + } else if( rn == 1 ) { + msg_category = "magic_8ball_unknown"; + color = m_info; + } else { + msg_category = "magic_8ball_good"; + color = m_good; + } + p->add_msg_if_player( color, _( "The %s says: %s" ), it->tname(), + SNIPPET.random_from_category( msg_category ).value_or( translation() ) ); return 0; } diff --git a/src/mapdata.cpp b/src/mapdata.cpp index 0a1ebfc43746f..eb72c8402c6b5 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -1301,6 +1301,7 @@ static cata::clone_ptr iexamine_actor_from_jsobj( const JsonObje void init_mapdata() { add_actor( std::make_unique() ); + add_actor( std::make_unique() ); } void map_data_common_t::load( const JsonObject &jo, const std::string & ) diff --git a/src/monster.cpp b/src/monster.cpp index a0c1900dd250f..3d1e87edf39a0 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -657,7 +657,12 @@ int monster::print_info( const catacurses::window &w, int vStart, int vLines, in type->src.end(), []( const std::pair &source ) { return string_format( "'%s'", source.second->name() ); }, enumeration_conjunction::arrow ); - oss << "" << "\n\n"; + oss << "" << "\n"; + + if( debug_mode ) { + oss << colorize( type->id.str(), c_white ); + } + oss << "\n"; // Print health bar, monster name, then statuses on the first line. nc_color bar_color = c_white; @@ -758,6 +763,11 @@ std::string monster::extended_description() const ss += "\n--\n"; + if( debug_mode ) { + ss += type->id.str(); + ss += "\n"; + } + ss += string_format( _( "This is a %s. %s %s" ), name(), att_colored, difficulty_str ) + "\n"; if( !get_effect_status().empty() ) { diff --git a/src/npctrade.cpp b/src/npctrade.cpp index a3cc56c8190be..ad58b3e39245d 100644 --- a/src/npctrade.cpp +++ b/src/npctrade.cpp @@ -568,6 +568,77 @@ int trading_window::get_var_trade( const item &it, int total_count ) return std::min( total_count, how_many ); } +void trading_window::item_selection( npc &np, std::vector &target_list, + item_pricing &ip, bool max ) +{ + int change_amount = 1; + int &owner_sells = focus_them ? ip.u_has : ip.npc_has; + int &owner_sells_charge = focus_them ? ip.u_charges : ip.npc_charges; + + if( ip.selected ) { + if( owner_sells_charge > 0 ) { + change_amount = owner_sells_charge; + owner_sells_charge = 0; + } else if( owner_sells > 0 ) { + change_amount = owner_sells; + owner_sells = 0; + // Deselect all contents when deselecting a container. + if( ip.is_container ) { + for( item *it : ip.loc.get_item()->get_contents().all_items_top() ) { + for( item_pricing &ipp : target_list ) { + if( it == ipp.loc.get_item() && ipp.selected ) { + item_selection( np, target_list, ipp ); + break; + } + } + } + } + } + } else if( ip.charges > 0 ) { + change_amount = max ? ip.charges : get_var_trade( *ip.loc.get_item(), ip.charges ); + + if( change_amount < 1 ) { + return; + } + owner_sells_charge = change_amount; + } else { + if( ip.count > 1 ) { + change_amount = max ? ip.count : get_var_trade( *ip.loc.get_item(), ip.count ); + + if( change_amount < 1 ) { + return; + } + } + owner_sells = change_amount; + // Select all contents when selecting a container. + if( ip.is_container ) { + for( item *it : ip.loc.get_item()->get_contents().all_items_top() ) { + for( item_pricing &ipp : target_list ) { + if( it == ipp.loc.get_item() && !ipp.selected ) { + item_selection( np, target_list, ipp, true ); + break; + } + } + } + } + } + ip.selected = !ip.selected; + if( ip.selected != focus_them ) { + change_amount *= -1; + } + int delta_price = ip.price * change_amount; + if( !np.will_exchange_items_freely() ) { + your_balance -= delta_price; + if( ip.selected != focus_them ) { + your_sale_value -= delta_price; + } + } + if( ip.loc.where_recursive() == item_location::type::character ) { + volume_left += ip.vol * change_amount; + weight_left += ip.weight * change_amount; + } +} + bool trading_window::perform_trade( npc &np, const std::string &deal ) { weight_left = np.weight_capacity() - np.weight_carried(); @@ -683,84 +754,7 @@ bool trading_window::perform_trade( npc &np, const std::string &deal ) ch += offset; if( ch < target_list.size() ) { item_pricing &ipr = target_list[ch]; - - // Recursive lambda https://artificial-mind.net/blog/2020/09/12/recursive-lambdas - auto item_selection = [ this, &np, &target_list ]( item_pricing & ip, - auto &&item_selection, bool max = false ) -> void { - int change_amount = 1; - int &owner_sells = focus_them ? ip.u_has : ip.npc_has; - int &owner_sells_charge = focus_them ? ip.u_charges : ip.npc_charges; - - if( ip.selected ) - { - if( owner_sells_charge > 0 ) { - change_amount = owner_sells_charge; - owner_sells_charge = 0; - } else if( owner_sells > 0 ) { - change_amount = owner_sells; - owner_sells = 0; - // Deselect all contents when deselecting a container. - if( ip.is_container ) { - for( item *it : ip.loc.get_item()->get_contents().all_items_top() ) { - for( item_pricing &ipp : target_list ) { - if( it == ipp.loc.get_item() && ipp.selected ) { - item_selection( ipp, item_selection ); - break; - } - } - } - } - } - } else if( ip.charges > 0 ) - { - change_amount = max ? ip.charges : get_var_trade( *ip.loc.get_item(), ip.charges ); - - if( change_amount < 1 ) { - return; - } - owner_sells_charge = change_amount; - } else - { - if( ip.count > 1 ) { - change_amount = max ? ip.count : get_var_trade( *ip.loc.get_item(), ip.count ); - - if( change_amount < 1 ) { - return; - } - } - owner_sells = change_amount; - // Select all contents when selecting a container. - if( ip.is_container ) { - for( item *it : ip.loc.get_item()->get_contents().all_items_top() ) { - for( item_pricing &ipp : target_list ) { - if( it == ipp.loc.get_item() && !ipp.selected ) { - item_selection( ipp, item_selection, true ); - break; - } - } - } - } - } - ip.selected = !ip.selected; - if( ip.selected != focus_them ) - { - change_amount *= -1; - } - int delta_price = ip.price * change_amount; - if( !np.will_exchange_items_freely() ) - { - your_balance -= delta_price; - if( ip.selected != focus_them ) { - your_sale_value -= delta_price; - } - } - if( ip.loc.where_recursive() == item_location::type::character ) - { - volume_left += ip.vol * change_amount; - weight_left += ip.weight * change_amount; - } - }; - item_selection( ipr, item_selection ); + item_selection( np, target_list, ipr ); } } } diff --git a/src/npctrade.h b/src/npctrade.h index 36625c3def543..5ddde36cb2198 100644 --- a/src/npctrade.h +++ b/src/npctrade.h @@ -76,6 +76,8 @@ class trading_window units::volume volume_left; units::mass weight_left; + void item_selection( npc &np, std::vector &target_list, + item_pricing &ip, bool max = false ); int get_var_trade( const item &it, int total_count ); bool npc_will_accept_trade( const npc &np ) const; int calc_npc_owes_you( const npc &np ) const; diff --git a/src/overmap.cpp b/src/overmap.cpp index 87d45cad5102b..d9bfebd4edda8 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1820,11 +1820,11 @@ struct mutable_overmap_special_data { return string_format( "%s: %s", io::enum_to_string( dir_join.first ), dir_join.second ); } ); - - debugmsg( "Spawn of mutable special %s had unresolved joins. Existing terrain " - "at %s was %s; joins were %s\nComplete record of placement follows:\n%s", - parent_id.str(), p.to_string(), current_terrain.id().str(), joins, - join( descriptions, "\n" ) ); + DebugLog( D_WARNING, D_MAIN ) << + string_format( "Spawn of mutable special %s had unresolved joins. Existing terrain " + "at %s was %s; joins were %s\nComplete record of placement follows:\n%s", + parent_id.str(), p.to_string(), current_terrain.id().str(), joins, + join( descriptions, "\n" ) ); om.add_note( p, string_format( diff --git a/src/overmap_ui.cpp b/src/overmap_ui.cpp index 5b8dccdb100f0..16dc4e9ef02fe 100644 --- a/src/overmap_ui.cpp +++ b/src/overmap_ui.cpp @@ -1072,10 +1072,10 @@ static void draw_om_sidebar( if( ( data.debug_editor && center_seen ) || data.debug_info ) { const oter_t &oter = overmap_buffer.ter( center ).obj(); - mvwprintz( wbar, point( 1, ++lines ), c_white, _( "oter: %s (rot %d)" ), oter.id.str(), + mvwprintz( wbar, point( 1, ++lines ), c_white, "oter: %s (rot %d)", oter.id.str(), oter.get_rotation() ); mvwprintz( wbar, point( 1, ++lines ), c_white, - _( "oter_type: %s" ), oter.get_type_id().str() ); + "oter_type: %s", oter.get_type_id().str() ); cata::optional *args = overmap_buffer.mapgen_args( center ); if( args ) { if( *args ) { @@ -1084,13 +1084,13 @@ static void draw_om_sidebar( arg.first, arg.second.get_string() ); } } else { - mvwprintz( wbar, point( 1, ++lines ), c_white, _( "args not yet set" ) ); + mvwprintz( wbar, point( 1, ++lines ), c_white, "args not yet set" ); } } for( cube_direction dir : all_enum_values() ) { if( std::string *join = overmap_buffer.join_used_at( { center, dir } ) ) { - mvwprintz( wbar, point( 1, ++lines ), c_white, _( "join %s: %s" ), + mvwprintz( wbar, point( 1, ++lines ), c_white, "join %s: %s", io::enum_to_string( dir ), *join ); } } diff --git a/src/weakpoint.cpp b/src/weakpoint.cpp index 87cdeb750234e..2085f599e6e82 100644 --- a/src/weakpoint.cpp +++ b/src/weakpoint.cpp @@ -154,9 +154,9 @@ void weakpoint::load( const JsonObject &jo ) assign( jo, "required_effects", required_effects ); } if( jo.has_array( "effects" ) ) { - for( const JsonObject jo : jo.get_array( "effects" ) ) { + for( const JsonObject effect_jo : jo.get_array( "effects" ) ) { weakpoint_effect effect; - effect.load( jo ); + effect.load( effect_jo ); effects.push_back( std::move( effect ) ); } } diff --git a/src/wish.cpp b/src/wish.cpp index f84be91c6faa0..6625c27eb889c 100644 --- a/src/wish.cpp +++ b/src/wish.cpp @@ -562,7 +562,7 @@ class wish_monster_callback: public uilist_callback if( valid_entnum ) { tmp.print_info( w_info, 2, 5, 1 ); - std::string header = string_format( "#%d: %s (%d)%s", entnum, tmp.type->nname(), + std::string header = string_format( "#%d: %s (%d)%s", entnum, tmp.type->id.str(), group, hallucination ? _( " (hallucination)" ) : "" ); mvwprintz( w_info, point( ( getmaxx( w_info ) - utf8_width( header ) ) / 2, 0 ), c_cyan, header ); }