[Scummvm-git-logs] scummvm master -> 8f38fdf700721cdf01443b5281675c0924b0687d

sev- noreply at scummvm.org
Fri Jul 3 15:17:26 UTC 2026


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
01ae727f47 HARVESTER: Address Coverity copy-instead-of-move warnings
70dbb47fe8 HARVESTER: Resolve Coverity dead code reports
7d0011204a HARVESTER: Avoid copying combat interaction results
8f38fdf700 HARVESTER: Move remaining state handoffs


Commit: 01ae727f47fe55f5eae1d1cb3160fcba7d20d219
    https://github.com/scummvm/scummvm/commit/01ae727f47fe55f5eae1d1cb3160fcba7d20d219
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-07-03T17:17:21+02:00

Commit Message:
HARVESTER: Address Coverity copy-instead-of-move warnings

Use Common::move when local parser records, interaction results, UI buffers, and media state are transferred into their final containers.

Keep intentional copies where the source is still live or comes from const runtime state, while making one-way handoffs explicit for static analysis.

Assisted-by: Codex:gpt-5.5

Changed paths:
    engines/harvester/dialogue.cpp
    engines/harvester/flow.cpp
    engines/harvester/fst_player.cpp
    engines/harvester/inventory.cpp
    engines/harvester/media_manager.cpp
    engines/harvester/menu.cpp
    engines/harvester/room.cpp
    engines/harvester/room_interaction.cpp
    engines/harvester/runtime_entity.cpp
    engines/harvester/script.cpp
    engines/harvester/text.cpp


diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index fce77fbff5e..7eb441f5c2f 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/dialogue.h"
 
+#include "common/algorithm.h"
 #include "common/debug.h"
 #include "common/endian.h"
 #include "common/events.h"
@@ -356,7 +357,7 @@ static void wrapDialogueTextLikeNative(const Graphics::Font &font, bool usesCft,
 
 	const int wrapCharsPerLine = width / MAX<int>(1, font.getCharWidth(' ') - 1);
 	if (wrapCharsPerLine <= 0) {
-		lines.push_back(wrappedText);
+		lines.push_back(Common::move(wrappedText));
 		return;
 	}
 
@@ -386,7 +387,7 @@ static void wrapDialogueTextLikeNative(const Graphics::Font &font, bool usesCft,
 	Common::String line;
 	for (uint i = 0; i < wrappedText.size(); ++i) {
 		if (wrappedText[i] == '\n') {
-			lines.push_back(line);
+			lines.push_back(Common::move(line));
 			line.clear();
 			continue;
 		}
@@ -395,7 +396,7 @@ static void wrapDialogueTextLikeNative(const Graphics::Font &font, bool usesCft,
 	}
 
 	if (!line.empty() || lines.empty())
-		lines.push_back(line);
+		lines.push_back(Common::move(line));
 }
 
 static void splitDialogueMenuLine(const Common::String &line, Common::Array<Common::String> &parts) {
@@ -406,7 +407,7 @@ static void splitDialogueMenuLine(const Common::String &line, Common::Array<Comm
 	Common::String token;
 	for (uint i = 0; i < line.size(); ++i) {
 		if (line[i] == '/') {
-			parts.push_back(token);
+			parts.push_back(Common::move(token));
 			token.clear();
 			continue;
 		}
@@ -414,7 +415,7 @@ static void splitDialogueMenuLine(const Common::String &line, Common::Array<Comm
 		token += line[i];
 	}
 
-	parts.push_back(token);
+	parts.push_back(Common::move(token));
 }
 
 static void logDialogueMenuItems(const char *label, int sourceLineIndex,
@@ -1199,7 +1200,7 @@ private:
 			}
 			option.rowCount = MAX<int>(1, option.wrappedLines.size());
 			totalRows += option.rowCount;
-			options.push_back(option);
+			options.push_back(Common::move(option));
 
 			explicitLines.clear();
 			optionText.clear();
@@ -1222,15 +1223,15 @@ private:
 
 				Common::String optionLine = segmentText.substr(digitEnd + 1);
 				optionLine.trim();
-				explicitLines.push_back(optionLine);
 				optionText = optionLine;
+				explicitLines.push_back(Common::move(optionLine));
 				return;
 			}
 
-			explicitLines.push_back(segmentText);
 			if (!optionText.empty())
 				optionText += ' ';
 			optionText += segmentText;
+			explicitLines.push_back(Common::move(segmentText));
 		};
 
 		for (uint i = 0; i < responseLine.size(); ++i) {
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index c5abbbed634..529913b05e1 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -23,6 +23,7 @@
 
 #include "harvester/flow.h"
 
+#include "common/algorithm.h"
 #include "common/config-manager.h"
 #include "common/debug.h"
 #include "common/endian.h"
@@ -802,7 +803,7 @@ bool loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resour
 	for (const ObjectRecord &object : state.activeObjects)
 		queueSceneObject("active", object, sceneObjects);
 
-	scene.sceneObjects = sceneObjects;
+	scene.sceneObjects = Common::move(sceneObjects);
 	for (const AnimRecord &anim : state.roomAnimations) {
 		if (shouldDisplaySceneAnimation(anim))
 			scene.sceneAnimations.push_back(anim);
@@ -1460,9 +1461,9 @@ bool Flow::loadQuickTips() {
 		if (ch == '\r')
 			continue;
 		if (ch == '\n') {
-			const Common::String trimmed = trimAsciiLine(currentLine);
+			Common::String trimmed = trimAsciiLine(currentLine);
 			if (!trimmed.empty())
-				_quickTips.push_back(trimmed);
+				_quickTips.push_back(Common::move(trimmed));
 			currentLine.clear();
 			continue;
 		}
@@ -1470,9 +1471,9 @@ bool Flow::loadQuickTips() {
 		currentLine += ch;
 	}
 
-	const Common::String trimmed = trimAsciiLine(currentLine);
+	Common::String trimmed = trimAsciiLine(currentLine);
 	if (!trimmed.empty())
-		_quickTips.push_back(trimmed);
+		_quickTips.push_back(Common::move(trimmed));
 
 	debugC(1, kDebugGeneral, "Harvester: loaded %u quick tips from '%s'", (uint)_quickTips.size(), kQuickTipsPath);
 	return true;
@@ -1501,7 +1502,7 @@ bool Flow::loadMenuItems() {
 		Common::String key = Common::String::format("main_menu_%u", i);
 		Common::String value;
 		if (menu.getKey(key, kMenuSectionName, value) && !value.empty())
-			_menuItems.push_back(value);
+			_menuItems.push_back(Common::move(value));
 	}
 
 	debugC(1, kDebugGeneral, "Harvester: loaded %u startup menu items from '%s'", (uint)_menuItems.size(), kMenuPath);
@@ -1789,7 +1790,7 @@ bool Flow::takeQueuedDialogueInteraction(InteractionResult &interaction) {
 	if (!_hasQueuedDialogueInteraction)
 		return false;
 
-	interaction = _queuedDialogueInteraction;
+	interaction = Common::move(_queuedDialogueInteraction);
 	_queuedDialogueInteraction = InteractionResult();
 	_hasQueuedDialogueInteraction = false;
 	return true;
@@ -1810,7 +1811,7 @@ bool Flow::takeQueuedDebugInteraction(InteractionResult &interaction) {
 	if (!_hasQueuedDebugInteraction)
 		return false;
 
-	interaction = _queuedDebugInteraction;
+	interaction = Common::move(_queuedDebugInteraction);
 	_queuedDebugInteraction = InteractionResult();
 	_hasQueuedDebugInteraction = false;
 	return true;
diff --git a/engines/harvester/fst_player.cpp b/engines/harvester/fst_player.cpp
index 76f2cee0e6b..7ff32453cd7 100644
--- a/engines/harvester/fst_player.cpp
+++ b/engines/harvester/fst_player.cpp
@@ -24,6 +24,7 @@
 #include "audio/audiostream.h"
 #include "audio/decoders/raw.h"
 #include "audio/mixer.h"
+#include "common/algorithm.h"
 #include "common/debug.h"
 #include "common/endian.h"
 #include "common/events.h"
@@ -509,7 +510,7 @@ bool FstPlayer::play(const Common::String &path) {
 		}
 
 		if (frameHasPalette) {
-			savedMoviePalette = framePalette;
+			savedMoviePalette = Common::move(framePalette);
 			haveSavedMoviePalette = true;
 		}
 
diff --git a/engines/harvester/inventory.cpp b/engines/harvester/inventory.cpp
index b71767acec9..5066f40a624 100644
--- a/engines/harvester/inventory.cpp
+++ b/engines/harvester/inventory.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/inventory.h"
 
+#include "common/algorithm.h"
 #include "common/debug.h"
 #include "common/endian.h"
 #include "graphics/blit.h"
@@ -311,7 +312,7 @@ bool InventorySystem::refresh() {
 
 		if (isExitObject(inventoryObject)) {
 			visual.bounds = getHotspotBounds(inventoryObject);
-			_items.push_back(visual);
+			_items.push_back(Common::move(visual));
 			continue;
 		}
 
@@ -321,7 +322,7 @@ bool InventorySystem::refresh() {
 			if (isStatusObject(inventoryObject)) {
 				visual.bounds = Common::Rect(visual.object.currentX, visual.object.currentY,
 					visual.object.currentX + visual.bitmap.width, visual.object.currentY + visual.bitmap.height);
-				_items.push_back(visual);
+				_items.push_back(Common::move(visual));
 				continue;
 			}
 
@@ -341,13 +342,13 @@ bool InventorySystem::refresh() {
 		}
 
 		if (isStatusObject(inventoryObject)) {
-			_items.push_back(visual);
 			debugLogInventoryVisual(visual, spritePath);
+			_items.push_back(Common::move(visual));
 			continue;
 		}
 
-		_items.push_back(visual);
 		debugLogInventoryVisual(visual, spritePath);
+		_items.push_back(Common::move(visual));
 	}
 
 	if (_selectedItemName.empty())
diff --git a/engines/harvester/media_manager.cpp b/engines/harvester/media_manager.cpp
index cf25a87c487..643034f469d 100644
--- a/engines/harvester/media_manager.cpp
+++ b/engines/harvester/media_manager.cpp
@@ -27,6 +27,7 @@
 #include "audio/audiostream.h"
 #include "audio/decoders/raw.h"
 #include "audio/decoders/wave.h"
+#include "common/algorithm.h"
 #include "common/endian.h"
 #include "common/memstream.h"
 #include "common/system.h"
@@ -291,7 +292,7 @@ bool MediaManager::playMusic(const Common::String &path) {
 	if (path.empty() || !g_system || !g_system->getMixer())
 		return false;
 
-	const Common::String normalizedPath = _resources.normalizeResourcePath(path);
+	Common::String normalizedPath = _resources.normalizeResourcePath(path);
 	if (_musicPath.equalsIgnoreCase(normalizedPath) &&
 			g_system->getMixer()->isSoundHandleActive(_musicHandle)) {
 		return true;
@@ -307,7 +308,7 @@ bool MediaManager::playMusic(const Common::String &path) {
 	stopMusic();
 	g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle,
 		Audio::makeLoopingAudioStream(audioStream, 0));
-	_musicPath = normalizedPath;
+	_musicPath = Common::move(normalizedPath);
 	return true;
 }
 
@@ -342,7 +343,7 @@ bool MediaManager::playSound(const Common::String &path) {
 	if (path.empty() || !g_system || !g_system->getMixer())
 		return false;
 
-	const Common::String normalizedPath = _resources.normalizeResourcePath(path);
+	Common::String normalizedPath = _resources.normalizeResourcePath(path);
 	for (int i = 0; i < ARRAYSIZE(_soundPaths); ++i) {
 		if (_soundPaths[i].equalsIgnoreCase(normalizedPath)) {
 			stopSoundHandle(_soundHandles[i]);
@@ -362,7 +363,7 @@ bool MediaManager::playSound(const Common::String &path) {
 
 	g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType,
 		&_soundHandles[_soundSlotIndex], audioStream);
-	_soundPaths[_soundSlotIndex] = normalizedPath;
+	_soundPaths[_soundSlotIndex] = Common::move(normalizedPath);
 	return true;
 }
 
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index e113074fb95..c87505235c5 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/menu.h"
 
+#include "common/algorithm.h"
 #include "common/config-manager.h"
 #include "common/endian.h"
 #include "common/events.h"
@@ -285,22 +286,22 @@ static bool loadMenuTextConfig(HarvesterEngine &engine, RoomMenuTextConfig &conf
 		const Common::String key = Common::String::format("options_menu_%u", i + 1);
 		Common::String value;
 		if (loadRawMenuValue(data, key.c_str(), value) && !value.empty())
-			config.optionItems[i] = value;
+			config.optionItems[i] = Common::move(value);
 		else if (menu.getKey(key, kMenuSectionName, value) && !value.empty())
-			config.optionItems[i] = value;
+			config.optionItems[i] = Common::move(value);
 	}
 
 	Common::String value;
 	if (menu.getKey("yes", kMenuSectionName, value) && !value.empty())
-		config.yesLabel = value;
+		config.yesLabel = Common::move(value);
 	if (menu.getKey("no", kMenuSectionName, value) && !value.empty())
-		config.noLabel = value;
+		config.noLabel = Common::move(value);
 	if (menu.getKey("click", kMenuSectionName, value) && !value.empty())
-		config.clickLabel = value;
+		config.clickLabel = Common::move(value);
 	if (loadRawMenuValue(data, "newgame", value) && !value.empty())
-		config.newGamePrompt = value;
+		config.newGamePrompt = Common::move(value);
 	if (loadRawMenuValue(data, "quitgame", value) && !value.empty())
-		config.quitGamePrompt = value;
+		config.quitGamePrompt = Common::move(value);
 
 	return true;
 }
@@ -484,13 +485,13 @@ static void splitMenuConfigLines(const Common::String &text, Common::Array<Commo
 	Common::String currentLine;
 	for (uint i = 0; i < text.size(); ++i) {
 		if (text[i] == '/') {
-			lines.push_back(currentLine);
+			lines.push_back(Common::move(currentLine));
 			currentLine.clear();
 			continue;
 		}
 		currentLine += text[i];
 	}
-	lines.push_back(currentLine);
+	lines.push_back(Common::move(currentLine));
 }
 
 static void renderOptionsMenuScreen(HarvesterEngine &engine, const IndexedBitmap &backdrop,
@@ -899,7 +900,7 @@ Common::Error MenuSystem::showGameOverBackdrop(Flow &flow) {
 		return Common::kReadingFailed;
 	}
 
-	_mainMenuBackdrop = backdrop;
+	_mainMenuBackdrop = Common::move(backdrop);
 	memcpy(_mainMenuBackdropPalette, palette, sizeof(_mainMenuBackdropPalette));
 	_hasMainMenuBackdrop = true;
 	flow.resetCursorAnimationSequence();
diff --git a/engines/harvester/room.cpp b/engines/harvester/room.cpp
index b3cbcade050..5d43435a9db 100644
--- a/engines/harvester/room.cpp
+++ b/engines/harvester/room.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/room.h"
 
+#include "common/algorithm.h"
 #include "common/endian.h"
 #include "common/events.h"
 #include "common/ptr.h"
@@ -934,7 +935,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 			if (!effectEntity)
 				return false;
 
-			hitEffectStates.push_back(effectState);
+			hitEffectStates.push_back(Common::move(effectState));
 			return true;
 		};
 		auto spawnCombatDamagePopup = [&](Entity &targetEntity,
@@ -947,7 +948,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 			popupState.startTick = Player::getRuntimeClockTicks();
 			popupState.damageAmount = damageAmount;
 			resolveCombatDamagePopupAnchor(targetEntity, popupState.anchorPoint);
-			damagePopupStates.push_back(popupState);
+			damagePopupStates.push_back(Common::move(popupState));
 		};
 		auto syncCombatHitEffects = [&]() {
 			if (!entityManager)
@@ -1122,13 +1123,13 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 			byte previousPalette[256 * 3];
 			memcpy(previousPalette, scene.palette, sizeof(previousPalette));
 			const float previousPaletteBrightness = scene.targetPaletteBrightness;
-			const Common::Array<AudioCommand> entryAudioCommands = scene.state.audioCommands;
+			Common::Array<AudioCommand> entryAudioCommands = scene.state.audioCommands;
 			RoomSetupState updatedState;
 			if (!script->materializeRoomState(
 					scene.state.entranceName, scene.state.roomName, updatedState, *resources)) {
 				return false;
 			}
-			updatedState.audioCommands = entryAudioCommands;
+			updatedState.audioCommands = Common::move(entryAudioCommands);
 
 			RoomSceneResources updatedScene;
 			if (!loadRoomSceneResources(updatedState, *resources, updatedScene))
@@ -1376,14 +1377,14 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 				(void)Player::setIdleAnimation(playerState, playerState.facing);
 		};
 		auto refreshCurrentScene = [&](bool preservePlayerPlacement) {
-			const Common::Array<AudioCommand> entryAudioCommands = scene.state.audioCommands;
+			Common::Array<AudioCommand> entryAudioCommands = scene.state.audioCommands;
 			RoomSetupState refreshedState;
 			if (!_engine.getScript()->materializeRoomState(
 					scene.state.entranceName, scene.state.roomName, refreshedState, *_engine.getResources())) {
 				return false;
 			}
 
-			refreshedState.audioCommands = entryAudioCommands;
+			refreshedState.audioCommands = Common::move(entryAudioCommands);
 			if (!loadRoomSceneResources(refreshedState, *_engine.getResources(), scene))
 				return false;
 			hitEffectStates.clear();
@@ -1658,7 +1659,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 					return Common::kNoError;
 				}
 
-				exitInteraction = continuationInteraction;
+				exitInteraction = Common::move(continuationInteraction);
 			}
 
 			warning("Harvester: room exit command chain for '%s' exceeded continuation safety limit",
@@ -2355,7 +2356,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 		if (script && !npc.onDeathActionTag.empty()) {
 			InteractionResult deathInteraction;
 			if (script->executeActionTag(npc.onDeathActionTag, deathInteraction, true, npc.roomName)) {
-				interaction = deathInteraction;
+				interaction = Common::move(deathInteraction);
 				interaction.mutatedRuntimeState = true;
 				interaction.visualRuntimeStateChanged = true;
 			}
@@ -2496,7 +2497,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 			InteractionResult deathInteraction;
 			if (script->executeActionTag(
 					monster->onDeathActionTag, deathInteraction, true, monster->roomName)) {
-				interaction = deathInteraction;
+				interaction = Common::move(deathInteraction);
 				interaction.mutatedRuntimeState = true;
 				interaction.visualRuntimeStateChanged = true;
 			}
@@ -2856,7 +2857,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 			InteractionResult deathInteraction;
 			if (script->executeActionTag(
 					monster->onDeathActionTag, deathInteraction, true, monster->roomName)) {
-				interaction = deathInteraction;
+				interaction = Common::move(deathInteraction);
 				interaction.mutatedRuntimeState = true;
 				interaction.visualRuntimeStateChanged = true;
 			}
@@ -2951,7 +2952,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 						InteractionResult deathInteraction;
 						if (script->executeActionTag(
 								monster.onDeathActionTag, deathInteraction, true, monster.roomName)) {
-							interaction = deathInteraction;
+							interaction = Common::move(deathInteraction);
 							interaction.mutatedRuntimeState = true;
 							interaction.visualRuntimeStateChanged = true;
 						}
diff --git a/engines/harvester/room_interaction.cpp b/engines/harvester/room_interaction.cpp
index 87337305134..cd42e26c22d 100644
--- a/engines/harvester/room_interaction.cpp
+++ b/engines/harvester/room_interaction.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/room_interaction.h"
 
+#include "common/algorithm.h"
 #include "common/debug.h"
 #include "common/textconsole.h"
 #include "harvester/art.h"
@@ -178,7 +179,7 @@ Common::Error RoomInteractionProcessor::handleInteractionResult(const Interactio
 			return exitError;
 
 		// Native CHANGE_ROOM queues a room handoff for the live loop instead of nesting.
-		_pendingRoomChange = resolvedTransitionTarget;
+		_pendingRoomChange = Common::move(resolvedTransitionTarget);
 		didTransition = true;
 	} else if (!interaction.nextRoomName.empty()) {
 		Common::Error exitError = _callbacks.runRoomExitCommands();
diff --git a/engines/harvester/runtime_entity.cpp b/engines/harvester/runtime_entity.cpp
index 38cf3b8eb44..f1a5083eeaa 100644
--- a/engines/harvester/runtime_entity.cpp
+++ b/engines/harvester/runtime_entity.cpp
@@ -23,6 +23,7 @@
 
 #include "harvester/runtime_entity.h"
 
+#include "common/algorithm.h"
 #include "common/debug.h"
 #include "common/endian.h"
 #include "common/system.h"
@@ -171,7 +172,7 @@ bool Entity::loadBitmapResource(ResourceManager &resources, const Common::String
 	memcpy(frame.pixels.data(), data.data() + 12, pixelCount);
 
 	_frames.clear();
-	_frames.push_back(frame);
+	_frames.push_back(Common::move(frame));
 	_baseFrames = _frames;
 	_resourcePath = path;
 	_currentFrame = 0;
@@ -764,7 +765,7 @@ void EntityManager::clearSceneEntities(bool preserveGlobalTimers) {
 
 		delete entity;
 	}
-	_sceneEntities = preservedEntities;
+	_sceneEntities = Common::move(preservedEntities);
 	_expiredTimerNames.clear();
 	_timerPauseDepth = 0;
 }
diff --git a/engines/harvester/script.cpp b/engines/harvester/script.cpp
index 4d926ab7c1b..d1a4ed3bf81 100644
--- a/engines/harvester/script.cpp
+++ b/engines/harvester/script.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/script.h"
 
+#include "common/algorithm.h"
 #include "common/config-manager.h"
 #include "common/debug.h"
 #include "common/endian.h"
@@ -460,7 +461,7 @@ static bool appendStartupAudioCommand(const CommandRecord &command, Common::Arra
 		AudioCommand audioCommand;
 		audioCommand.type = kStartupAudioCommandStartWav;
 		audioCommand.path = command.arg1;
-		commands.push_back(audioCommand);
+		commands.push_back(Common::move(audioCommand));
 		return true;
 	}
 
@@ -468,7 +469,7 @@ static bool appendStartupAudioCommand(const CommandRecord &command, Common::Arra
 		AudioCommand audioCommand;
 		audioCommand.type = kStartupAudioCommandStartSingleWav;
 		audioCommand.path = command.arg1;
-		commands.push_back(audioCommand);
+		commands.push_back(Common::move(audioCommand));
 		return true;
 	}
 
@@ -477,7 +478,7 @@ static bool appendStartupAudioCommand(const CommandRecord &command, Common::Arra
 		audioCommand.type = kStartupAudioCommandLoadWav;
 		audioCommand.path = command.arg1;
 		audioCommand.slot = command.arg2.empty() ? -1 : parseAsciiIntOrZero(command.arg2);
-		commands.push_back(audioCommand);
+		commands.push_back(Common::move(audioCommand));
 		return true;
 	}
 
@@ -485,7 +486,7 @@ static bool appendStartupAudioCommand(const CommandRecord &command, Common::Arra
 		AudioCommand audioCommand;
 		audioCommand.type = kStartupAudioCommandPlayWav;
 		audioCommand.slot = command.arg1.empty() ? -1 : parseAsciiIntOrZero(command.arg1);
-		commands.push_back(audioCommand);
+		commands.push_back(Common::move(audioCommand));
 		return true;
 	}
 
@@ -493,7 +494,7 @@ static bool appendStartupAudioCommand(const CommandRecord &command, Common::Arra
 		AudioCommand audioCommand;
 		audioCommand.type = kStartupAudioCommandDeleteWav;
 		audioCommand.slot = command.arg1.empty() ? -1 : parseAsciiIntOrZero(command.arg1);
-		commands.push_back(audioCommand);
+		commands.push_back(Common::move(audioCommand));
 		return true;
 	}
 
@@ -551,14 +552,14 @@ static void tokenizeTownScriptLine(const Common::String &line, Common::Array<Com
 				token += line[i++];
 			if (i < line.size() && line[i] == '"')
 				++i;
-			tokens.push_back(token);
+			tokens.push_back(Common::move(token));
 			continue;
 		}
 
 		Common::String token;
 		while (i < line.size() && line[i] != ' ' && line[i] != '\t')
 			token += line[i++];
-		tokens.push_back(token);
+		tokens.push_back(Common::move(token));
 	}
 }
 
@@ -954,7 +955,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			flag.name = tokens[tagIndex + 1];
 			flag.value = tokens[tagIndex + 2].equalsIgnoreCase("T");
 			if (!flag.name.empty())
-				_flags.push_back(flag);
+				_flags.push_back(Common::move(flag));
 			return;
 		}
 
@@ -980,7 +981,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			}
 
 			if (!command.triggerTag.empty() && !command.opcodeName.empty())
-				_commands.push_back(command);
+				_commands.push_back(Common::move(command));
 			return;
 		}
 
@@ -996,7 +997,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 				execList.entries.push_back(tokens[i]);
 			}
 			if (!execList.listName.empty())
-				_execLists.push_back(execList);
+				_execLists.push_back(Common::move(execList));
 			return;
 		}
 
@@ -1013,7 +1014,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 					textRecord.value.setChar(' ', i);
 			}
 			if (!textRecord.key.empty())
-				_texts.push_back(textRecord);
+				_texts.push_back(Common::move(textRecord));
 			return;
 		}
 
@@ -1025,7 +1026,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			head.headId = tokens[tagIndex + 1];
 			head.portraitPath = resources.normalizeResourcePath(tokens[tagIndex + 2]);
 			if (!head.headId.empty() && !head.portraitPath.empty())
-				_heads.push_back(head);
+				_heads.push_back(Common::move(head));
 			return;
 		}
 
@@ -1039,7 +1040,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			useItem.targetName = tokens[tagIndex + 3];
 			useItem.actionTag = tokens[tagIndex + 4];
 			if (!useItem.itemName.empty() && !useItem.targetName.empty())
-				_useItems.push_back(useItem);
+				_useItems.push_back(Common::move(useItem));
 			return;
 		}
 
@@ -1058,7 +1059,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			entrance.roomName = tokens[tagIndex + 2];
 			entrance.entranceName = tokens[tagIndex + 3];
 			if (!entrance.roomName.empty() && !entrance.entranceName.empty())
-				_entrances.push_back(entrance);
+				_entrances.push_back(Common::move(entrance));
 			return;
 		}
 
@@ -1074,7 +1075,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			}
 			mapEntrance.entryName = tokens[tagIndex + 1];
 			if (!mapEntrance.entryName.empty())
-				_mapEntrances.push_back(mapEntrance);
+				_mapEntrances.push_back(Common::move(mapEntrance));
 			return;
 		}
 
@@ -1099,7 +1100,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			}
 			mapLocation.destinationEntranceName = tokens[tagIndex + 2];
 			if (!mapLocation.destinationEntranceName.empty())
-				_mapLocations.push_back(mapLocation);
+				_mapLocations.push_back(Common::move(mapLocation));
 			return;
 		}
 
@@ -1130,7 +1131,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			room.onEnterCommand = tokens[tagIndex + 8];
 			room.onExitCommand = tokens[tagIndex + 9];
 			if (!room.roomName.empty())
-				_rooms.push_back(room);
+				_rooms.push_back(Common::move(room));
 			return;
 		}
 
@@ -1158,7 +1159,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			npc.audioPath = resources.normalizeResourcePath(tokens[tagIndex + 8]);
 			npc.entityInitArg = tokens[tagIndex + 9];
 			if (!npc.roomName.empty() && !npc.modelPath.empty() && !npc.npcName.empty())
-				_npcs.push_back(npc);
+				_npcs.push_back(Common::move(npc));
 			return;
 		}
 
@@ -1213,7 +1214,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 				monster.visible = true;
 			if (!monster.roomName.empty() && !monster.monsterName.empty() && !monster.modelPath.empty()) {
 				monster.recordIndex = (int)_monsters.size();
-				_monsters.push_back(monster);
+				_monsters.push_back(Common::move(monster));
 			}
 			return;
 		}
@@ -1234,7 +1235,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			timer.looping = tokens[tagIndex + 5].equalsIgnoreCase("T");
 			timer.global = tokens[tagIndex + 6].equalsIgnoreCase("T");
 			if (!timer.timerName.empty())
-				_timers.push_back(timer);
+				_timers.push_back(Common::move(timer));
 			return;
 		}
 
@@ -1259,7 +1260,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			region.startEnabled = tokens[tagIndex + 5].equalsIgnoreCase("T");
 			region.cursorEnabled = tokens[tagIndex + 6].equalsIgnoreCase("T");
 			if (!region.roomName.empty() && !region.regionName.empty())
-				_regions.push_back(region);
+				_regions.push_back(Common::move(region));
 			return;
 		}
 
@@ -1286,7 +1287,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			anim.runtimeActive = anim.active;
 			anim.runtimeVisible = anim.visible;
 			if (!anim.roomName.empty() && !anim.resourcePath.empty() && !anim.animName.empty())
-				_animations.push_back(anim);
+				_animations.push_back(Common::move(anim));
 			return;
 		}
 
@@ -1325,7 +1326,7 @@ void Script::parseTownRecords(ResourceManager &resources) {
 			object.objectName = Common::String::format("__ANON_OBJECT_%u", anonymousObjectId++);
 		}
 		if (!object.initialOwnerOrRoom.empty())
-			_objects.push_back(object);
+			_objects.push_back(Common::move(object));
 		};
 
 	Common::String line;
@@ -1848,7 +1849,7 @@ bool Script::executeDebugCommand(const CommandRecord &command,
 
 	CommandRecord debugCommand = command;
 	debugCommand.triggerTag = debugTag;
-	_commands.push_back(debugCommand);
+	_commands.push_back(Common::move(debugCommand));
 	const bool handled = executeActionTag(debugTag, result, allowTransitions);
 	_commands.pop_back();
 	return handled;
@@ -1983,7 +1984,7 @@ void Script::getVisibleInventoryObjects(Common::Array<ObjectRecord> &objects) co
 	activeStatusObject.visible = true;
 	activeStatusObject.runtimeVisible = true;
 	activeStatusObject.identShown = true;
-	objects.push_back(activeStatusObject);
+	objects.push_back(Common::move(activeStatusObject));
 }
 
 bool Script::isObjectInInventory(const Common::String &objectName) const {
@@ -2835,7 +2836,7 @@ void Script::executeCommandChain(const Common::String &initialTag, const char *c
 				FlagRecord newFlag;
 				newFlag.name = command->arg1;
 				newFlag.value = flagValue;
-				_currentFlags.push_back(newFlag);
+				_currentFlags.push_back(Common::move(newFlag));
 				changed = true;
 			}
 			debugC(1, kDebugGeneral,
@@ -3536,7 +3537,7 @@ bool Script::setRuntimeFlagValue(const Common::String &flagName, bool value) {
 	FlagRecord newFlag;
 	newFlag.name = flagName;
 	newFlag.value = value;
-	_currentFlags.push_back(newFlag);
+	_currentFlags.push_back(Common::move(newFlag));
 	debugC(1, kDebugGeneral,
 		"Harvester: direct runtime flag '%s' %d -> %d existed=0 changed=1",
 		flagName.c_str(), 0, value);
diff --git a/engines/harvester/text.cpp b/engines/harvester/text.cpp
index 4984e8be46f..9ea13bd6fe3 100644
--- a/engines/harvester/text.cpp
+++ b/engines/harvester/text.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/text.h"
 
+#include "common/algorithm.h"
 #include "common/config-manager.h"
 #include "common/debug.h"
 #include "common/endian.h"
@@ -60,7 +61,7 @@ static void parseDialogueResponseLines(const Common::Array<byte> &responseData,
 		if (value == '\r')
 			continue;
 		if (value == '\n') {
-			lines.push_back(line);
+			lines.push_back(Common::move(line));
 			line.clear();
 			continue;
 		}
@@ -69,7 +70,7 @@ static void parseDialogueResponseLines(const Common::Array<byte> &responseData,
 	}
 
 	if (!line.empty())
-		lines.push_back(line);
+		lines.push_back(Common::move(line));
 }
 
 static bool hasNativeHankDialogueResponseLayout(const Common::Array<Common::String> &lines) {
@@ -110,7 +111,7 @@ static bool tryLoadPreferredDialogueResponsesFromGamePath(Common::Array<Common::
 		Common::Array<Common::String> candidateLines;
 		if (loadDialogueResponseLinesFromNode(candidate, candidateLines) &&
 				hasNativeHankDialogueResponseLayout(candidateLines)) {
-			lines = candidateLines;
+			lines = Common::move(candidateLines);
 			debug(1, "Harvester: using native-compatible DIALOG.RSP from '%s'",
 				candidate.getPath().toString(Common::Path::kNativeSeparator).c_str());
 			return true;
@@ -181,7 +182,7 @@ bool Text::loadDialogueIndex(ResourceManager &resources) {
 		entry.textLength = MIN<uint32>(cursor - entry.textOffset, 0x19a);
 
 		if (entry.wavId > 0 && entry.textLength != 0)
-			_dialogueEntries.push_back(entry);
+			_dialogueEntries.push_back(Common::move(entry));
 	}
 
 	return !_dialogueEntries.empty();
@@ -201,7 +202,7 @@ bool Text::loadDialogueResponses(ResourceManager &resources) {
 	if (!hasNativeHankDialogueResponseLayout(_dialogueResponseLines)) {
 		Common::Array<Common::String> preferredLines;
 		if (tryLoadPreferredDialogueResponsesFromGamePath(preferredLines))
-			_dialogueResponseLines = preferredLines;
+			_dialogueResponseLines = Common::move(preferredLines);
 	}
 
 	return !_dialogueResponseLines.empty();
@@ -236,7 +237,7 @@ bool Text::loadFont(ResourceManager &resources, const Common::String &path) {
 	font.atlasPixels.resize(pixelCount);
 	memcpy(font.atlasPixels.data(), data.data() + kCftBitmapHeaderSize, pixelCount);
 
-	_fonts.push_back(font);
+	_fonts.push_back(Common::move(font));
 	return true;
 }
 


Commit: 70dbb47fe8df88cf47e9d385ae962423b0a0ff01
    https://github.com/scummvm/scummvm/commit/70dbb47fe8df88cf47e9d385ae962423b0a0ff01
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-07-03T17:17:21+02:00

Commit Message:
HARVESTER: Resolve Coverity dead code reports

Remove logically unreachable branches from the debug command parser, room menu activation flow, and combat target selection.

The command parser now returns after consuming a final CHAIN option instead of tracking a flag that could never be observed twice. The room menu activation helper returns both its error and close-menu state explicitly, avoiding hidden state that looked contradictory to static analysis. Combat target helpers now take proven non-null monster records by reference and only guard the nullable call site.

Assisted-by: Codex:gpt-5.5

Changed paths:
    engines/harvester/console.cpp
    engines/harvester/menu.cpp
    engines/harvester/room.cpp


diff --git a/engines/harvester/console.cpp b/engines/harvester/console.cpp
index e70946b77be..023d58d2217 100644
--- a/engines/harvester/console.cpp
+++ b/engines/harvester/console.cpp
@@ -323,14 +323,9 @@ static bool parseDebugCommandArgs(int argc, const char **argv, CommandRecord &co
 
 	command.opcodeName = argv[1];
 	uint positionalArgIndex = 0;
-	bool sawChain = false;
 	for (int i = 2; i < argc; ++i) {
 		const Common::String token = argv[i];
 		if (token.equalsIgnoreCase("CHAIN")) {
-			if (sawChain) {
-				errorMessage = "CHAIN may only be specified once";
-				return false;
-			}
 			if (i + 1 >= argc) {
 				errorMessage = "CHAIN requires an action tag";
 				return false;
@@ -340,8 +335,7 @@ static bool parseDebugCommandArgs(int argc, const char **argv, CommandRecord &co
 				return false;
 			}
 			command.arg4 = argv[i + 1];
-			sawChain = true;
-			break;
+			return true;
 		}
 
 		// Positional args map directly onto the startup command fields, with arg4 also
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index c87505235c5..7b5d6fea140 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -967,12 +967,17 @@ Common::Error MenuSystem::runRoomMenuStub(const IndexedBitmap &backdrop, const b
 		roomMenuItems);
 	int selectedItem = roomMenuItems.empty() ? -1 : 0;
 	bool needsRedraw = true;
-	bool shouldCloseMenu = false;
 	flow.resetCursorAnimationSequence();
 
-	auto activateSelectedItem = [&]() -> Common::Error {
+	struct RoomMenuActivationResult {
+		Common::Error error;
+		bool closeMenu;
+
+		RoomMenuActivationResult(Common::Error e, bool c) : error(e), closeMenu(c) {}
+	};
+	auto activateSelectedItem = [&]() -> RoomMenuActivationResult {
 		if (selectedItem < 0 || selectedItem >= (int)roomMenuItems.size())
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, false);
 
 		const Common::String &item = roomMenuItems[selectedItem];
 		if (item.equalsIgnoreCase("NEW GAME")) {
@@ -983,70 +988,67 @@ Common::Error MenuSystem::runRoomMenuStub(const IndexedBitmap &backdrop, const b
 			Common::Error confirmError = runConfirmPrompt(
 				backdrop, palette, paletteBrightness, flow, config.newGamePrompt, confirmed);
 			if (confirmError.getCode() != Common::kNoError)
-				return confirmError;
+				return RoomMenuActivationResult(confirmError, false);
 			needsRedraw = true;
 			if (confirmed) {
 				flow.requestNewGameRestart();
-				shouldCloseMenu = true;
+				return RoomMenuActivationResult(Common::kNoError, true);
 			}
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, false);
 		}
 
 		if (item.equalsIgnoreCase("LOAD GAME")) {
 			bool loadedGame = false;
 			Common::Error loadError = runLoadGameMenu(palette, paletteBrightness, flow, loadedGame);
 			if (loadError.getCode() != Common::kNoError)
-				return loadError;
+				return RoomMenuActivationResult(loadError, false);
 			needsRedraw = true;
-			if (loadedGame)
-				shouldCloseMenu = true;
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, loadedGame);
 		}
 
 		if (item.equalsIgnoreCase("OPTIONS")) {
 			Common::Error optionsError = runOptionsMenu(backdrop, palette, paletteBrightness, flow);
 			if (optionsError.getCode() != Common::kNoError)
-				return optionsError;
+				return RoomMenuActivationResult(optionsError, false);
 			needsRedraw = true;
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, false);
 		}
 
 		if (item.equalsIgnoreCase("HELP")) {
 			Common::Error helpError = runHelpScreen(palette, paletteBrightness, flow);
 			if (helpError.getCode() != Common::kNoError)
-				return helpError;
+				return RoomMenuActivationResult(helpError, false);
 			needsRedraw = true;
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, false);
 		}
 
 		if (item.equalsIgnoreCase("SAVE GAME")) {
 			bool savedGame = false;
 			Common::Error saveError = runSaveGameMenu(palette, paletteBrightness, flow, savedGame);
 			if (saveError.getCode() != Common::kNoError)
-				return saveError;
+				return RoomMenuActivationResult(saveError, false);
 			if (savedGame) {
 				// Native exits the in-room ESC menu after a successful save and restores the room view.
 				Common::Error restoreError = restoreRoomBackdropAfterSave(
 					backdrop, palette, paletteBrightness, flow);
 				if (restoreError.getCode() != Common::kNoError)
-					return restoreError;
-				shouldCloseMenu = true;
-				return Common::kNoError;
+					return RoomMenuActivationResult(restoreError, false);
+				return RoomMenuActivationResult(Common::kNoError, true);
 			}
 			needsRedraw = true;
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, false);
 		}
 
 		if (item.equalsIgnoreCase("QUIT GAME")) {
 			Common::Error quitError = runQuitGameConfirm(backdrop, palette, paletteBrightness, flow);
 			if (quitError.getCode() != Common::kNoError)
-				return quitError;
+				return RoomMenuActivationResult(quitError, false);
 			needsRedraw = true;
-			return Common::kNoError;
+			return RoomMenuActivationResult(Common::kNoError, false);
 		}
 
 		debug(1, "Harvester: room menu item '%s' selected but not implemented", item.c_str());
-		return Common::kNoError;
+		return RoomMenuActivationResult(Common::kNoError, false);
 	};
 
 	while (!_engine.shouldQuit()) {
@@ -1085,11 +1087,10 @@ Common::Error MenuSystem::runRoomMenuStub(const IndexedBitmap &backdrop, const b
 					needsRedraw = true;
 				} else if (event.kbd.keycode == Common::KEYCODE_RETURN ||
 						event.kbd.keycode == Common::KEYCODE_KP_ENTER) {
-					shouldCloseMenu = false;
-					Common::Error activateError = activateSelectedItem();
-					if (activateError.getCode() != Common::kNoError)
-						return activateError;
-					if (shouldCloseMenu)
+					RoomMenuActivationResult activationResult = activateSelectedItem();
+					if (activationResult.error.getCode() != Common::kNoError)
+						return activationResult.error;
+					if (activationResult.closeMenu)
 						return Common::kNoError;
 				}
 				break;
@@ -1101,11 +1102,10 @@ Common::Error MenuSystem::runRoomMenuStub(const IndexedBitmap &backdrop, const b
 				if (selectedItem == -1)
 					break;
 
-				shouldCloseMenu = false;
-				Common::Error activateError = activateSelectedItem();
-				if (activateError.getCode() != Common::kNoError)
-					return activateError;
-				if (shouldCloseMenu)
+				RoomMenuActivationResult activationResult = activateSelectedItem();
+				if (activationResult.error.getCode() != Common::kNoError)
+					return activationResult.error;
+				if (activationResult.closeMenu)
 					return Common::kNoError;
 				break;
 			}
diff --git a/engines/harvester/room.cpp b/engines/harvester/room.cpp
index 5d43435a9db..38f052525b0 100644
--- a/engines/harvester/room.cpp
+++ b/engines/harvester/room.cpp
@@ -2371,19 +2371,19 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 		auto isKillableMonster = [&](const MonsterRecord *monster) {
 			return monster && monster->active && monster->visible && monster->currentHitPoints > 0;
 		};
-		auto selectMonsterEntity = [&](MonsterRecord *monster) -> Entity * {
-			Entity *entity = monster ? findSceneRuntimeEntity(monster->monsterName) : nullptr;
+		auto selectMonsterEntity = [&](const MonsterRecord &monster) -> Entity * {
+			Entity *entity = findSceneRuntimeEntity(monster.monsterName);
 			return (entity && entity->isVisible()) ? entity : nullptr;
 		};
 		auto resolveKillTarget = [&]() -> MonsterRecord * {
 			if (playerState.attackTargetClassId == kRuntimeEntityClassMonster) {
 				MonsterRecord *monster = findRoomMonsterRecordByName(playerState.attackTargetName);
-				if (isKillableMonster(monster) && selectMonsterEntity(monster))
+				if (isKillableMonster(monster) && selectMonsterEntity(*monster))
 					return monster;
 			}
 
 			if (MonsterRecord *monster = findMonsterTargetAtPoint(_mousePos)) {
-				if (isKillableMonster(monster) && selectMonsterEntity(monster))
+				if (isKillableMonster(monster) && selectMonsterEntity(*monster))
 					return monster;
 			}
 
@@ -2391,7 +2391,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 				for (uint i = 0; i < scene.state.roomMonsters.size() && i < monsterCombatStates.size(); ++i) {
 					MonsterRecord &monster = scene.state.roomMonsters[i];
 					const RoomMonsterCombatState &combatState = monsterCombatStates[i];
-					if (!combatState.attackActive || !isKillableMonster(&monster) || !selectMonsterEntity(&monster))
+					if (!combatState.attackActive || !isKillableMonster(&monster) || !selectMonsterEntity(monster))
 						continue;
 					if (!combatState.attackTargetName.empty() &&
 							playerState.entity->getName().equalsIgnoreCase(combatState.attackTargetName)) {
@@ -2411,7 +2411,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 				if (!isKillableMonster(&monster))
 					continue;
 
-				Entity *entity = selectMonsterEntity(&monster);
+				Entity *entity = selectMonsterEntity(monster);
 				if (!entity)
 					continue;
 
@@ -2429,7 +2429,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 		};
 
 		MonsterRecord *monster = resolveKillTarget();
-		Entity *monsterEntity = selectMonsterEntity(monster);
+		Entity *monsterEntity = monster ? selectMonsterEntity(*monster) : nullptr;
 		if (!monster || !monsterEntity) {
 			debugC(1, kDebugCombat,
 				"Harvester: debug combat kill skipped reason='no active monster' cursor=(%d,%d)",
@@ -2773,7 +2773,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 		if (playerState.attackTargetClassId == kRuntimeEntityClassMonster)
 			monster = findRoomMonsterRecordByName(playerState.attackTargetName);
 		Entity *monsterEntity = monster ? findSceneRuntimeEntity(monster->monsterName) : nullptr;
-		if (!monster || !monsterEntity || !playerAttackCanReachTarget(monsterEntity, monster ? monster->engageDistance : 0)) {
+		if (!monster || !monsterEntity || !playerAttackCanReachTarget(monsterEntity, monster->engageDistance)) {
 			if (!Player::isProjectileCombatLoadout(playerState.combatLoadout)) {
 				monster = findOverlappingMonsterTarget();
 			} else if (playerState.attackTargetClassId < 0) {


Commit: 7d0011204af8749532c2477e4642832dd1f74b93
    https://github.com/scummvm/scummvm/commit/7d0011204af8749532c2477e4642832dd1f74b93
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-07-03T17:17:21+02:00

Commit Message:
HARVESTER: Avoid copying combat interaction results

Pass the combat interaction helper parameter by const reference.

The helper only forwards the interaction result to RoomInteractionProcessor, whose API already accepts a const reference. Keeping the same ownership and mutation behavior avoids copying the large result object during combat updates.

Assisted-by: Codex:gpt-5.5

Changed paths:
    engines/harvester/room.cpp


diff --git a/engines/harvester/room.cpp b/engines/harvester/room.cpp
index 38f052525b0..fbbe6067b51 100644
--- a/engines/harvester/room.cpp
+++ b/engines/harvester/room.cpp
@@ -2268,7 +2268,7 @@ Common::Error RoomSystem::runRoomLoop(Flow &flow, const Common::String &targetNa
 			return "none";
 		}
 	};
-	auto handleCombatInteraction = [&](InteractionResult interaction) -> Common::Error {
+	auto handleCombatInteraction = [&](const InteractionResult &interaction) -> Common::Error {
 		bool didTransition = false;
 		Common::Error interactionError =
 			interactionProcessor.handleInteractionResult(interaction, didTransition, Common::String());


Commit: 8f38fdf700721cdf01443b5281675c0924b0687d
    https://github.com/scummvm/scummvm/commit/8f38fdf700721cdf01443b5281675c0924b0687d
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-07-03T17:17:21+02:00

Commit Message:
HARVESTER: Move remaining state handoffs

Use Common::move when save/load and script reload paths transfer local buffers into engine state.

The loaded dialogue blob and reloaded town script data are no longer needed after assignment. The pending loaded room state is also moved after the current save state copy, logging, and disc capture have consumed the original value.

Assisted-by: Codex:gpt-5.5

Changed paths:
    engines/harvester/saveload.cpp
    engines/harvester/script.cpp


diff --git a/engines/harvester/saveload.cpp b/engines/harvester/saveload.cpp
index 5ba9628c66d..d3ad83d8de2 100644
--- a/engines/harvester/saveload.cpp
+++ b/engines/harvester/saveload.cpp
@@ -21,6 +21,7 @@
 
 #include "harvester/harvester.h"
 
+#include "common/algorithm.h"
 #include "common/serializer.h"
 #include "harvester/detection.h"
 #include "harvester/flow.h"
@@ -229,7 +230,7 @@ Common::Error HarvesterEngine::syncGame(Common::Serializer &s) {
 	}
 	s.syncBytes(dialogueStateBlob.data(), dialogueStateSize);
 	if (s.isLoading()) {
-		_pendingLoadedDialogueStateBlob = dialogueStateBlob;
+		_pendingLoadedDialogueStateBlob = Common::move(dialogueStateBlob);
 		_pendingLoadedDialogueStateBlobVersion = s.getVersion();
 	}
 	if (s.err())
@@ -240,10 +241,11 @@ Common::Error HarvesterEngine::syncGame(Common::Serializer &s) {
 			return Common::kReadingFailed;
 		if (!prepareLoadedRoomDisc(*this, roomState, restoredDisc))
 			return Common::kReadingFailed;
-		_currentSaveRoomState = roomState;
-		_pendingLoadedSaveRoomState = roomState;
-		_pendingLoadedDisc = roomState.discNumber;
+		const int pendingLoadedDisc = roomState.discNumber;
 		logStartupSaveRoomState("loaded", roomState);
+		_currentSaveRoomState = roomState;
+		_pendingLoadedSaveRoomState = Common::move(roomState);
+		_pendingLoadedDisc = pendingLoadedDisc;
 	}
 	return Common::kNoError;
 }
diff --git a/engines/harvester/script.cpp b/engines/harvester/script.cpp
index d1a4ed3bf81..2ea1c39bff9 100644
--- a/engines/harvester/script.cpp
+++ b/engines/harvester/script.cpp
@@ -644,7 +644,7 @@ bool Script::reloadTownWorld(ResourceManager &resources) {
 	const int playerCombatLoadout = _playerCombatLoadout;
 	const bool playerControlPaused = _playerControlPaused;
 
-	_data = reloadedData;
+	_data = Common::move(reloadedData);
 	decode();
 	parseTownRecords(resources);
 	resetRuntimeState();




More information about the Scummvm-git-logs mailing list