[Scummvm-git-logs] scummvm master -> d092cf2688ceb23ae0bcc091b780e802a56c8384
alexbevi
noreply at scummvm.org
Sat Oct 17 12:38:37 UTC 2026
This automated email contains information about 21 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
1d9db0c28e HARVESTER: get rid of duplicated clipped transparent bitmap implementations
19926d2016 HARVESTER: add text editing helpers
41f2eba3b0 HARVESTER: refactor save/load to use a common slot system
a8a11fd66c HARVESTER: refactor NPC dialogue handling
8ae6a2999b HARVESTER: refactor player state management
852752b953 HARVESTER: improve Combat design
a99abfd26a HARVESTER: add an explicit execution context for scripts
4c2cd50a79 HARVESTER: Move font lookup into Text
736efc4b9d HARVESTER: Move scene drawing into RoomPresentation
3099689314 HARVESTER: Replace Flow access bridge with explicit operations
704302dcdc HARVESTER: Encapsulate remaining Flow state access
102331f518 HARVESTER: Remove remaining Flow friendships
bad29b7c89 HARVESTER: Share room object entity construction
41fbd50e02 HARVESTER: Share NPC animation configuration
0c2252ad15 HARVESTER: Share monster entity construction
db94aa0a4e HARVESTER: Share region entity construction
88ff885adb HARVESTER: Move inspect text rendering into RoomPresentation
9f90244baa HARVESTER: Move scene record lookups into SceneEntities
fb53fc9838 HARVESTER: Move scene resource assembly into SceneEntities
bdb15ec5f3 HARVESTER: Move hover resolution into Input
d092cf2688 HARVESTER: Fix cursor freezing after idle animations
Commit: 1d9db0c28ecfdc324afae1e95375d7df6dda0e12
https://github.com/scummvm/scummvm/commit/1d9db0c28ecfdc324afae1e95375d7df6dda0e12
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:06-04:00
Commit Message:
HARVESTER: get rid of duplicated clipped transparent bitmap implementations
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/art.cpp
engines/harvester/art.h
engines/harvester/bitmap.cpp
engines/harvester/bitmap.h
engines/harvester/dialogue.cpp
engines/harvester/entity.cpp
engines/harvester/flow.cpp
engines/harvester/inventory.cpp
engines/harvester/menu.cpp
engines/harvester/npc/chessmaster_dialogue.cpp
engines/harvester/room_presentation.cpp
engines/harvester/room_presentation.h
engines/harvester/scene.cpp
diff --git a/engines/harvester/art.cpp b/engines/harvester/art.cpp
index aab5aed1950..702c04b1966 100644
--- a/engines/harvester/art.cpp
+++ b/engines/harvester/art.cpp
@@ -22,7 +22,6 @@
#include "harvester/art.h"
#include "common/debug.h"
-#include "graphics/blit.h"
#include "graphics/screen.h"
#include "harvester/detection.h"
#include "harvester/palette_utils.h"
@@ -196,41 +195,6 @@ bool Art::loadAnimation(ResourceManager &resources, const Common::String &path,
return true;
}
-void Art::blitTransparentBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) const {
- if (!bitmap.isValid())
- return;
-
- int srcX = 0;
- int srcY = 0;
- int destX = x;
- int destY = y;
- int width = (int)bitmap.width;
- int height = (int)bitmap.height;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = bitmap.pixels.data() + srcY * bitmap.width + srcX;
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, bitmap.width, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
-}
-
void Art::blitTransparentAnimationFrame(Graphics::Screen &screen, const Common::Array<AbmFrame> &frames,
uint frameIndex, int x, int y) const {
if (frameIndex >= frames.size() || !frames[frameIndex].isValid())
diff --git a/engines/harvester/art.h b/engines/harvester/art.h
index 3877523750e..1b810560a21 100644
--- a/engines/harvester/art.h
+++ b/engines/harvester/art.h
@@ -53,7 +53,6 @@ private:
bool loadPalette(ResourceManager &resources, const Common::String &path, byte *dest) const;
bool loadBitmap(ResourceManager &resources, const Common::String &path, IndexedBitmap &bitmap) const;
bool loadAnimation(ResourceManager &resources, const Common::String &path, Common::Array<AbmFrame> &frames) const;
- void blitTransparentBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) const;
void blitTransparentAnimationFrame(Graphics::Screen &screen, const Common::Array<AbmFrame> &frames,
uint frameIndex, int x, int y) const;
diff --git a/engines/harvester/bitmap.cpp b/engines/harvester/bitmap.cpp
index 1d1d8df4143..42abf72d726 100644
--- a/engines/harvester/bitmap.cpp
+++ b/engines/harvester/bitmap.cpp
@@ -23,10 +23,24 @@
#include "common/debug.h"
#include "common/endian.h"
+#include "graphics/managed_surface.h"
#include "harvester/detection.h"
namespace Harvester {
+void blitTransparentBitmap(Graphics::ManagedSurface &surface, const IndexedBitmap &bitmap, int x, int y) {
+ if (!bitmap.isValid() || x >= surface.w || y >= surface.h ||
+ x <= -(int)bitmap.width || y <= -(int)bitmap.height)
+ return;
+
+ Graphics::ManagedSurface source;
+ // Borrow the bitmap pixels without taking ownership.
+ source.surfacePtr()->init(bitmap.width, bitmap.height, bitmap.width,
+ const_cast<byte *>(bitmap.pixels.data()), Graphics::PixelFormat::createFormatCLUT8());
+ source.setTransparentColor(0);
+ surface.simpleBlitFrom(source, Common::Point(x, y));
+}
+
namespace {
static bool decodeAnimationFrame(const byte *source, uint32 sourceSize, bool compressed, Common::Array<byte> &dest) {
diff --git a/engines/harvester/bitmap.h b/engines/harvester/bitmap.h
index 9a87c2cbcaa..40cc0a26066 100644
--- a/engines/harvester/bitmap.h
+++ b/engines/harvester/bitmap.h
@@ -24,6 +24,10 @@
#include "common/array.h"
+namespace Graphics {
+class ManagedSurface;
+}
+
namespace Harvester {
struct IndexedBitmap {
@@ -41,6 +45,9 @@ struct AbmFrame : IndexedBitmap {
int32 yOffset = 0;
};
+// Draw unscaled pixels with index 0 transparent; callers supply the final position.
+void blitTransparentBitmap(Graphics::ManagedSurface &surface, const IndexedBitmap &bitmap, int x, int y);
+
// Callers choose when to clear output. Failed decoding can leave partial header or frame data.
bool decodeBitmap(const Common::Array<byte> &data, IndexedBitmap &bitmap);
bool decodeAbm(const Common::Array<byte> &data, Common::Array<AbmFrame> &frames);
diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index b0a65e07877..4835f476fe5 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -26,7 +26,6 @@
#include "common/events.h"
#include "common/ptr.h"
#include "common/system.h"
-#include "graphics/blit.h"
#include "graphics/font.h"
#include "graphics/fontman.h"
#include "graphics/framelimiter.h"
@@ -150,7 +149,6 @@ static const char *const kDialogueLocalizedKeywordBitmapPath = "GRAPHIC/OTHER/KE
static const byte kTextColorNormal = 255;
static const byte kTextColorHover = 251;
static const byte kShadowColor = 0;
-static const byte kTransparentPaletteIndex = 0;
static bool isDialogueVoiceInterruptEvent(const Common::Event &event) {
return event.type == Common::EVENT_LBUTTONDOWN ||
@@ -229,41 +227,6 @@ static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, in
screen.copyRectToSurface(bitmap.pixels.data(), bitmap.width, x, y, bitmap.width, bitmap.height);
}
-static void blitTransparentBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
- if (!bitmap.isValid())
- return;
-
- int srcX = 0;
- int srcY = 0;
- int destX = x;
- int destY = y;
- int width = (int)bitmap.width;
- int height = (int)bitmap.height;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = bitmap.pixels.data() + srcY * bitmap.width + srcX;
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, bitmap.width, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
-}
-
static void drawShadowedString(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
int x, int y, int width, byte color, Graphics::TextAlign align = Graphics::kTextAlignLeft) {
font.drawString(&screen, text, x + 1, y + 1, width, kShadowColor, align);
diff --git a/engines/harvester/entity.cpp b/engines/harvester/entity.cpp
index 0a4a2e13de6..0cacae75e36 100644
--- a/engines/harvester/entity.cpp
+++ b/engines/harvester/entity.cpp
@@ -66,39 +66,8 @@ static void scaleIndexedBitmapNearest(const IndexedBitmap &source, IndexedBitmap
static void blitAnimationFrame(Graphics::Screen &screen, const Common::Array<AbmFrame> &frames, uint frameIndex,
int x, int y) {
- if (frameIndex >= frames.size() || !frames[frameIndex].isValid())
- return;
-
- const AbmFrame &frame = frames[frameIndex];
- int destX = x;
- int destY = y;
- int srcX = 0;
- int srcY = 0;
- int width = (int)frame.width;
- int height = (int)frame.height;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = frame.pixels.data() + srcY * frame.width + srcX;
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, frame.width, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
+ if (frameIndex < frames.size())
+ blitTransparentBitmap(screen, frames[frameIndex], x, y);
}
} // End of anonymous namespace
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 3e40804f3d4..21bc79e07d5 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -32,7 +32,6 @@
#include "common/ptr.h"
#include "common/serializer.h"
#include "common/system.h"
-#include "graphics/blit.h"
#include "graphics/font.h"
#include "graphics/fontman.h"
#include "graphics/framelimiter.h"
@@ -586,26 +585,6 @@ static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, in
screen.copyRectToSurface(bitmap.pixels.data(), bitmap.width, x, y, bitmap.width, bitmap.height);
}
-static void blitTransparentBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap,
- int x, int y) {
- if (!bitmap.isValid())
- return;
-
- for (uint32 srcY = 0; srcY < bitmap.height; ++srcY) {
- const int destY = y + (int)srcY;
- if (destY < 0 || destY >= screen.h)
- continue;
- for (uint32 srcX = 0; srcX < bitmap.width; ++srcX) {
- const int destX = x + (int)srcX;
- if (destX < 0 || destX >= screen.w)
- continue;
- const byte color = bitmap.pixels[srcY * bitmap.width + srcX];
- if (color != 0)
- *(byte *)screen.getBasePtr(destX, destY) = color;
- }
- }
-}
-
bool captureScreenBackdrop(const Graphics::Screen &screen, IndexedBitmap &bitmap) {
if (screen.w <= 0 || screen.h <= 0 || screen.format.bytesPerPixel != 1)
return false;
diff --git a/engines/harvester/inventory.cpp b/engines/harvester/inventory.cpp
index 3054f5e7705..5670dc0a88c 100644
--- a/engines/harvester/inventory.cpp
+++ b/engines/harvester/inventory.cpp
@@ -23,7 +23,6 @@
#include "common/algorithm.h"
#include "common/debug.h"
-#include "graphics/blit.h"
#include "graphics/font.h"
#include "graphics/screen.h"
#include "harvester/detection.h"
@@ -43,7 +42,6 @@ static const int kInventoryItemStartX = 73;
static const int kInventoryItemStartY = 115;
static const int kInventoryItemMaxRight = 564;
static const int kInventoryItemSpacing = 5;
-static const byte kTransparentPaletteIndex = 0;
static const char *const kHarvestBladeObjectName = "HARVEST_BLADE";
struct InventoryCombatLoadoutEntry {
@@ -113,41 +111,6 @@ static const char *const kInventoryObjectActionItems[] = {
"ST_VITAMN"
};
-static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
- if (!bitmap.isValid())
- return;
-
- int destX = x;
- int destY = y;
- int srcX = 0;
- int srcY = 0;
- int width = (int)bitmap.width;
- int height = (int)bitmap.height;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = bitmap.pixels.data() + srcY * bitmap.width + srcX;
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, bitmap.width, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
-}
-
static Common::Rect getHotspotBounds(const ObjectRecord &object) {
if (object.boundsX2 > object.currentX && object.boundsY2 > object.currentY)
return Common::Rect(object.currentX, object.currentY, object.boundsX2 + 1, object.boundsY2 + 1);
@@ -526,7 +489,7 @@ void InventorySystem::drawSelectedDragItem(Graphics::Screen &screen, const Commo
const int drawX = point.x - (int)item.bitmap.width / 2;
const int drawY = point.y - (int)item.bitmap.height / 2;
- blitBitmap(screen, item.bitmap, drawX, drawY);
+ blitTransparentBitmap(screen, item.bitmap, drawX, drawY);
return;
}
}
@@ -536,13 +499,13 @@ void InventorySystem::drawOverlay(Graphics::Screen &screen) const {
if (!art)
return;
- blitBitmap(screen, art->getInventoryBitmap(), kInventoryX, kInventoryY);
+ blitTransparentBitmap(screen, art->getInventoryBitmap(), kInventoryX, kInventoryY);
for (const InventoryVisual &item : _items) {
if (!_selectedItemName.empty() && item.object.objectName.equalsIgnoreCase(_selectedItemName))
continue;
if (item.hasBitmap && item.bitmap.isValid())
- blitBitmap(screen, item.bitmap, item.object.currentX, item.object.currentY);
+ blitTransparentBitmap(screen, item.bitmap, item.object.currentX, item.object.currentY);
}
}
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index 0a60adc48f4..01a98a7cfc4 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -28,7 +28,6 @@
#include "common/memstream.h"
#include "common/system.h"
#include "engines/metaengine.h"
-#include "graphics/blit.h"
#include "graphics/font.h"
#include "graphics/fontman.h"
#include "graphics/framelimiter.h"
@@ -60,7 +59,6 @@ static const byte kTextColorHover = 251;
static const byte kTextColorDim = 248;
static const byte kShadowColor = 0;
static const byte kPanelFillColor = 1;
-static const byte kTransparentPaletteIndex = 0;
static const byte kQuickTipActionColor = 0xc3;
static const char *const kMenuPath = "MENU.INI";
@@ -527,41 +525,6 @@ static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, in
screen.copyRectToSurface(bitmap.pixels.data(), bitmap.width, x, y, bitmap.width, bitmap.height);
}
-static void blitTransparentBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
- if (!bitmap.isValid())
- return;
-
- int srcX = 0;
- int srcY = 0;
- int destX = x;
- int destY = y;
- int width = (int)bitmap.width;
- int height = (int)bitmap.height;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = bitmap.pixels.data() + srcY * bitmap.width + srcX;
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, bitmap.width, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
-}
-
static void drawShadowedString(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
int x, int y, int width, byte color, Graphics::TextAlign align = Graphics::kTextAlignLeft) {
font.drawString(&screen, text, x + 1, y + 1, width, kShadowColor, align);
diff --git a/engines/harvester/npc/chessmaster_dialogue.cpp b/engines/harvester/npc/chessmaster_dialogue.cpp
index 0cebc88beb4..ad4a21c3002 100644
--- a/engines/harvester/npc/chessmaster_dialogue.cpp
+++ b/engines/harvester/npc/chessmaster_dialogue.cpp
@@ -24,7 +24,6 @@
#include "common/events.h"
#include "common/system.h"
-#include "graphics/blit.h"
#include "graphics/framelimiter.h"
#include "graphics/screen.h"
#include "harvester/harvester.h"
@@ -40,7 +39,6 @@ static const char *const kChessmasterNpc = "CHESSMASTER";
static const char *const kChessSolvedFlag = "CHESS_SOLVED";
static const char *const kChessKingMonsterActionTag = "ADD_CHESS_KING_MONSTER";
static const int kChessmasterSlashDamageType = 2;
-static const byte kTransparentPaletteIndex = 0;
static const uint32 kChessmasterSuccessHoldMs = 1000;
struct ChessmasterHotspot {
@@ -128,41 +126,6 @@ static bool pointHitsAnyHotspot(const Common::Point &point, const ChessmasterHot
return false;
}
-static void blitTransparentFrame(Graphics::Screen &screen, const Graphics::Surface &frame, int x, int y) {
- if (frame.w <= 0 || frame.h <= 0)
- return;
-
- int destX = x;
- int destY = y;
- int srcX = 0;
- int srcY = 0;
- int width = frame.w;
- int height = frame.h;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = (const byte *)frame.getBasePtr(srcX, srcY);
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, frame.pitch, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
-}
-
static Common::Error decodeInitialFlicFrame(DialogueRuntime &runtime, const char *path,
ChessmasterFlicState &state) {
ResourceManager *resources = runtime.engine().getResources();
@@ -333,7 +296,7 @@ static Common::Error runChessmasterChoiceStage(DialogueRuntime &runtime,
drawFlicFrame(*screen, background);
const ChessmasterFlicState &cursorState = onInteractiveHotspot ? operateCursor : pointer;
if (cursorState.frame)
- blitTransparentFrame(*screen, *cursorState.frame, mousePos.x, mousePos.y);
+ screen->transBlitFrom(*cursorState.frame, mousePos, 0);
screen->makeAllDirty();
screen->update();
diff --git a/engines/harvester/room_presentation.cpp b/engines/harvester/room_presentation.cpp
index 7cfc3505581..024c15148c6 100644
--- a/engines/harvester/room_presentation.cpp
+++ b/engines/harvester/room_presentation.cpp
@@ -26,7 +26,6 @@
#include "common/events.h"
#include "common/system.h"
#include "common/textconsole.h"
-#include "graphics/blit.h"
#include "graphics/framelimiter.h"
#include "harvester/art.h"
#include "harvester/detection.h"
@@ -38,7 +37,6 @@
namespace Harvester {
-static const byte kTransparentPaletteIndex = 0;
static const float kNormalPaletteBrightness = 1.0f;
static const float kDimPaletteBrightness = 0.6f;
@@ -58,41 +56,6 @@ static void setScaledRoomPalette(Graphics::Screen &screen, const byte *palette,
screen.setPalette(scaledPalette);
}
-void RoomPresentation::blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
- if (!bitmap.isValid())
- return;
-
- int destX = x;
- int destY = y;
- int srcX = 0;
- int srcY = 0;
- int width = (int)bitmap.width;
- int height = (int)bitmap.height;
-
- if (destX < 0) {
- srcX = -destX;
- width += destX;
- destX = 0;
- }
- if (destY < 0) {
- srcY = -destY;
- height += destY;
- destY = 0;
- }
- if (destX >= screen.w || destY >= screen.h || width <= 0 || height <= 0)
- return;
-
- width = MIN<int>(width, screen.w - destX);
- height = MIN<int>(height, screen.h - destY);
- if (width <= 0 || height <= 0)
- return;
-
- const byte *src = bitmap.pixels.data() + srcY * bitmap.width + srcX;
- byte *dst = (byte *)screen.getBasePtr(destX, destY);
- Graphics::keyBlit(dst, src, screen.pitch, bitmap.width, width, height,
- screen.format.bytesPerPixel, kTransparentPaletteIndex);
-}
-
RoomPresentation::RoomPresentation(HarvesterEngine &engine, SceneState &scene,
const Art *art, const Graphics::Font *inspectFont, bool useNativeInspectFont)
: _engine(engine), _scene(scene), _art(art), _inspectFont(inspectFont),
@@ -208,7 +171,7 @@ Common::Error RoomPresentation::runModalShowText(const ResolvedText &modalText,
if (!initialInputReleased && frameCount++ > 0)
initialInputReleased = true;
- blitBitmap(*activeScreen, backdrop, 0, 0);
+ blitTransparentBitmap(*activeScreen, backdrop, 0, 0);
setScaledRoomPalette(*activeScreen, _scene.palette, _scene.targetPaletteBrightness);
drawRoomInspectText(*activeScreen, *_art, *_inspectFont, modalText, _useNativeInspectFont);
activeScreen->makeAllDirty();
diff --git a/engines/harvester/room_presentation.h b/engines/harvester/room_presentation.h
index 93ecb8985f8..d5f39737f9d 100644
--- a/engines/harvester/room_presentation.h
+++ b/engines/harvester/room_presentation.h
@@ -66,7 +66,6 @@ public:
bool captureDialogueBackdrop(IndexedBitmap &dialogueBackdrop);
Common::Error applyLightingCommand(StartupLightingCommand lightingCommand);
Common::Error runModalShowText(const ResolvedText &modalText, Flow &flow);
- static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y);
private:
HarvesterEngine &_engine;
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index c66b32a234b..63a04825872 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -117,7 +117,7 @@ static void drawCombatLoadoutResourceIcons(Graphics::Screen &screen, const Art &
const int iconCount = CLIP<int>(script.getPlayerCombatResourceCount(loadout), 0, info.maxVisibleCount);
for (int i = 0; i < iconCount; ++i)
- RoomPresentation::blitBitmap(screen, icon, kNativeCombatResourceIconsX + i * kNativeCombatResourceIconSpacing,
+ blitTransparentBitmap(screen, icon, kNativeCombatResourceIconsX + i * kNativeCombatResourceIconSpacing,
kNativeCombatResourceIconsY);
}
@@ -562,7 +562,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
} else if (roomCarryActive && _roomItems.getCarriedRoomItemBitmap().isValid()) {
const int drawX = _flow._mousePos.x - (int)_roomItems.getCarriedRoomItemBitmap().width / 2;
const int drawY = _flow._mousePos.y - (int)_roomItems.getCarriedRoomItemBitmap().height / 2;
- RoomPresentation::blitBitmap(*activeScreen, _roomItems.getCarriedRoomItemBitmap(), drawX, drawY);
+ blitTransparentBitmap(*activeScreen, _roomItems.getCarriedRoomItemBitmap(), drawX, drawY);
}
if (_presentationState.showingInspectText) {
Commit: 19926d2016cd25cacd6e1837b8256b1c5104763d
https://github.com/scummvm/scummvm/commit/19926d2016cd25cacd6e1837b8256b1c5104763d
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:06-04:00
Commit Message:
HARVESTER: add text editing helpers
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/dialogue.cpp
engines/harvester/text.cpp
engines/harvester/text.h
diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index 4835f476fe5..80d29481e48 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -768,19 +768,17 @@ public:
cancelInput = true;
} else if (event.kbd.keycode == Common::KEYCODE_BACKSPACE ||
event.kbd.keycode == Common::KEYCODE_LEFT) {
- if (!typedTopic.empty())
- typedTopic.deleteLastChar();
+ deleteTextEntryCharacter(typedTopic);
} else if (event.kbd.keycode == Common::KEYCODE_HOME) {
typedTopic.clear();
} else if (event.kbd.keycode == Common::KEYCODE_RETURN ||
event.kbd.keycode == Common::KEYCODE_KP_ENTER) {
acceptInput = true;
} else if (event.kbd.ascii >= 0x1f && event.kbd.ascii <= 0x80 &&
- event.kbd.ascii != '~' && typedTopic.size() < kDialogueTextEntryMaxLength &&
+ event.kbd.ascii != '~' &&
(!_subtitleCftFont || _subtitleCftFont->hasGlyph(event.kbd.ascii))) {
- typedTopic += (char)event.kbd.ascii;
- if (_highlightFont->getStringWidth(typedTopic) > kDialogueTextEntryMaxWidth)
- typedTopic.deleteLastChar();
+ appendTextEntryCharacter(typedTopic, *_highlightFont, event.kbd.ascii,
+ kDialogueTextEntryMaxLength, kDialogueTextEntryMaxWidth);
}
} else if (event.type == Common::EVENT_LBUTTONDOWN) {
acceptInput = Common::Rect(3, 460, 318, 477).contains(event.mouse);
diff --git a/engines/harvester/text.cpp b/engines/harvester/text.cpp
index d2a61cc6754..dffc9693187 100644
--- a/engines/harvester/text.cpp
+++ b/engines/harvester/text.cpp
@@ -28,12 +28,33 @@
#include "common/fs.h"
#include "common/ptr.h"
#include "common/stream.h"
+#include "graphics/font.h"
#include "harvester/harvester.h"
#include "harvester/parse_utils.h"
#include "harvester/resources.h"
namespace Harvester {
+bool appendTextEntryCharacter(Common::String &text, const Graphics::Font &font,
+ uint32 character, uint maxCharacters, int maxWidth) {
+ if (text.size() >= maxCharacters)
+ return false;
+
+ const Common::String candidate = text + (char)character;
+ if (font.getStringWidth(candidate) > maxWidth)
+ return false;
+
+ text = candidate;
+ return true;
+}
+
+bool deleteTextEntryCharacter(Common::String &text) {
+ if (text.empty())
+ return false;
+ text.deleteLastChar();
+ return true;
+}
+
namespace {
static const char *const kStartupFontPaths[] = {
diff --git a/engines/harvester/text.h b/engines/harvester/text.h
index c73d3b8086f..3d64d0879ba 100644
--- a/engines/harvester/text.h
+++ b/engines/harvester/text.h
@@ -25,10 +25,18 @@
#include "common/array.h"
#include "common/str.h"
+namespace Graphics {
+class Font;
+}
+
namespace Harvester {
class ResourceManager;
+bool appendTextEntryCharacter(Common::String &text, const Graphics::Font &font,
+ uint32 character, uint maxCharacters, int maxWidth);
+bool deleteTextEntryCharacter(Common::String &text);
+
struct DialogueIndexEntry {
int wavId = 0;
uint32 textOffset = 0;
Commit: 41f2eba3b07420a459a68675f36499a00c959904
https://github.com/scummvm/scummvm/commit/41f2eba3b07420a459a68675f36499a00c959904
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:06-04:00
Commit Message:
HARVESTER: refactor save/load to use a common slot system
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/menu.cpp
engines/harvester/menu.h
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index 01a98a7cfc4..0e83333470b 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -497,23 +497,6 @@ static Common::String buildOptionsMenuItemLabel(const Script &script,
}
}
-static bool appendBoundedTextEntryCharacter(Common::String &text, const Graphics::Font &font,
- uint32 ascii, uint maxCharacters, int maxWidth) {
- if (ascii < 32 || ascii > 126 || ascii == '~' || text.size() >= maxCharacters)
- return false;
-
- const Common::String candidate = text + (char)ascii;
- if (font.getStringWidth(candidate) > maxWidth)
- return false;
-
- text = candidate;
- return true;
-}
-
-static bool appendInlineSaveCharacter(Common::String &text, const Graphics::Font &font, uint32 ascii) {
- return appendBoundedTextEntryCharacter(text, font, ascii, kSaveSlotMaxCharacters, kSaveSlotTextWidth);
-}
-
static Common::String buildDefaultSaveSlotLabel(int slotIndex) {
return Common::String::format("GAME %02d", slotIndex + 1);
}
@@ -656,43 +639,6 @@ static void renderQuickTipsOverlay(HarvesterEngine &engine, const IndexedBitmap
screen->update();
}
-static void renderSaveGameMenuScreen(HarvesterEngine &engine, const IndexedBitmap &background,
- const byte *palette, float paletteBrightness, const Graphics::Font &selectedLabelFont,
- const Graphics::Font &unselectedLabelFont, const Graphics::Font &slotNameFont,
- const Common::Array<Common::String> &slotTitles, int activeSlot,
- const Common::String &statusMessage, int editingSlot = -1,
- const Common::String *editingText = nullptr) {
- Graphics::Screen *screen = engine.getScreen();
- if (!screen)
- return;
-
- applyMenuPalette(*screen, engine, palette, paletteBrightness);
- blitBitmap(*screen, background, 0, 0);
-
- for (int i = 0; i < kSaveSlotCount; ++i) {
- const Graphics::Font &labelFont = (i == activeSlot) ? selectedLabelFont : unselectedLabelFont;
- const int y = kSaveSlotStartY + i * kSaveSlotStride;
- const Common::String slotLabel = buildDefaultSaveSlotLabel(i);
- labelFont.drawString(screen, slotLabel, kSaveSlotLabelX, y,
- labelFont.getStringWidth(slotLabel), 0);
-
- Common::String displayTitle = slotTitles[i];
- if (i == editingSlot && editingText)
- displayTitle = *editingText + "_";
- slotNameFont.drawString(screen, displayTitle, kSaveSlotNameX, y, kSaveSlotTextWidth, 0);
- }
-
- if (!statusMessage.empty()) {
- drawShadowedString(*screen, slotNameFont, statusMessage, 20, kSaveStatusTextY,
- screen->w - 40, kTextColorNormal, Graphics::kTextAlignCenter);
- }
-
- if (engine.getRuntimeEntities())
- engine.getRuntimeEntities()->drawCursor(*screen);
- screen->makeAllDirty();
- screen->update();
-}
-
static void renderConfirmPromptScreen(HarvesterEngine &engine, const IndexedBitmap &backdrop,
const byte *palette, float paletteBrightness, const Graphics::Font &promptFont,
const Graphics::Font &yesFont, const Graphics::Font &noFont,
@@ -1363,86 +1309,97 @@ Common::Error MenuSystem::runRoomMenu(const IndexedBitmap &backdrop, const byte
return Common::kNoError;
}
-Common::Error MenuSystem::runLoadGameMenu(const byte *palette, float paletteBrightness,
- Flow &flow, bool &loadedGame) {
- (void)palette;
- (void)paletteBrightness;
- loadedGame = false;
-
- ResourceManager *resources = _engine.getResources();
- MetaEngine *metaEngine = _engine.getMetaEngine();
- const CftFontResource *slotNameFontResource = findStartupFontByName(_engine, "MEDFONT1");
- const CftFontResource *slotLabelFontResource = findStartupFontByName(_engine, "MEDFONT2");
- if (!resources || !metaEngine || !slotNameFontResource || !slotLabelFontResource)
- return Common::kReadingFailed;
- if (!_engine.canLoadGameStateCurrently())
- return Common::kNoError;
-
- HarvesterCftFont slotNameFont(*slotNameFontResource);
- HarvesterCftFont slotLabelFont(*slotLabelFontResource);
- if (!slotNameFont.isValid() || !slotLabelFont.isValid())
- return Common::kReadingFailed;
+struct MenuSystem::SaveSlotMenu {
+ SaveSlotMenu(MetaEngine &meta, const CftFontResource &nameFont, const CftFontResource &labelFont)
+ : metaEngine(meta), slotNameFont(nameFont), slotLabelFont(labelFont) {}
+ MetaEngine &metaEngine;
+ HarvesterCftFont slotNameFont;
+ HarvesterCftFont slotLabelFont;
IndexedBitmap background;
- byte loadPalette[256 * 3];
- if (!loadBitmapResource(*resources, kLoadGameBitmapPath, background) ||
- !loadPaletteResource(*resources, kLoadGamePalettePath, loadPalette)) {
- return Common::kReadingFailed;
- }
-
+ byte palette[256 * 3];
Common::Array<Common::String> slotTitles;
- slotTitles.resize(kSaveSlotCount);
- for (int i = 0; i < kSaveSlotCount; ++i)
- slotTitles[i].clear();
+ int activeSlot = 0;
+ Common::String statusMessage;
+ bool needsRedraw = true;
+};
- const SaveStateList saves = metaEngine->listSaves(ConfMan.getActiveDomainName().c_str());
+void MenuSystem::reloadSaveSlotTitles(SaveSlotMenu &menu) const {
+ menu.slotTitles.clear();
+ menu.slotTitles.resize(kSaveSlotCount);
+ const SaveStateList saves = menu.metaEngine.listSaves(ConfMan.getActiveDomainName().c_str());
for (const SaveStateDescriptor &save : saves) {
const int slot = save.getSaveSlot();
- if (slot < 0 || slot >= kSaveSlotCount)
- continue;
- slotTitles[slot] = save.getDescription();
+ if (slot >= 0 && slot < kSaveSlotCount)
+ menu.slotTitles[slot] = save.getDescription();
}
+}
- auto resolveHoveredSlot = [&]() -> int {
- for (int slot = 0; slot < kSaveSlotCount; ++slot) {
- if (saveSlotRect(slot).contains(_mousePos))
- return slot;
- }
- return -1;
- };
-
- int activeSlot = 0;
+int MenuSystem::getSaveSlotAt(const Common::Point &mousePos) const {
for (int slot = 0; slot < kSaveSlotCount; ++slot) {
- if (!slotTitles[slot].empty()) {
- activeSlot = slot;
- break;
- }
+ if (saveSlotRect(slot).contains(mousePos))
+ return slot;
}
+ return -1;
+}
- Common::String statusMessage;
- bool needsRedraw = true;
- flow.resetCursorAnimationSequence();
- Graphics::FrameLimiter limiter(g_system, 60);
+MenuSystem::SaveSlotCommand MenuSystem::getSaveSlotCommand(const Common::Event &event) const {
+ if (event.type == Common::EVENT_KEYDOWN) {
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
+ return kCancelSlot;
+ if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_KP_ENTER)
+ return kConfirmSlot;
+ } else if (event.type == Common::EVENT_LBUTTONDOWN) {
+ if (saveConfirmRect().contains(_mousePos))
+ return kConfirmSlot;
+ if (saveCancelRect().contains(_mousePos))
+ return kCancelSlot;
+ }
+ return kNoSlotCommand;
+}
- auto activateSelectedSlot = [&]() -> Common::Error {
- if (slotTitles[activeSlot].empty())
- return Common::kNoError;
+void MenuSystem::renderSaveSlotMenu(const SaveSlotMenu &menu, const Common::String *editingText) const {
+ Graphics::Screen *screen = _engine.getScreen();
+ if (!screen)
+ return;
- Common::Error loadError = _engine.loadGameState(activeSlot);
- if (loadError.getCode() == Common::kNoError) {
- loadedGame = true;
- return Common::kNoError;
- }
+ applyMenuPalette(*screen, _engine, menu.palette, 1.0f);
+ blitBitmap(*screen, menu.background, 0, 0);
- statusMessage = loadError.getDesc();
- needsRedraw = true;
- return Common::kNoError;
- };
+ for (int i = 0; i < kSaveSlotCount; ++i) {
+ const Graphics::Font &labelFont = (i == menu.activeSlot) ? menu.slotNameFont : menu.slotLabelFont;
+ const int y = kSaveSlotStartY + i * kSaveSlotStride;
+ const Common::String slotLabel = buildDefaultSaveSlotLabel(i);
+ labelFont.drawString(screen, slotLabel, kSaveSlotLabelX, y,
+ labelFont.getStringWidth(slotLabel), 0);
+
+ Common::String displayTitle = menu.slotTitles[i];
+ if (i == menu.activeSlot && editingText)
+ displayTitle = *editingText + "_";
+ menu.slotNameFont.drawString(screen, displayTitle, kSaveSlotNameX, y, kSaveSlotTextWidth, 0);
+ }
+
+ if (!editingText && !menu.statusMessage.empty()) {
+ drawShadowedString(*screen, menu.slotNameFont, menu.statusMessage, 20, kSaveStatusTextY,
+ screen->w - 40, kTextColorNormal, Graphics::kTextAlignCenter);
+ }
+
+ if (_engine.getRuntimeEntities())
+ _engine.getRuntimeEntities()->drawCursor(*screen);
+ screen->makeAllDirty();
+ screen->update();
+}
+
+Common::Error MenuSystem::runSaveSlotEditor(SaveSlotMenu &menu, Flow &flow,
+ Common::String &editedTitle, bool &confirmed) {
+ confirmed = false;
+ bool needsRedraw = true;
+ flow.resetCursorAnimationSequence();
+ Graphics::FrameLimiter limiter(g_system, 60);
while (!_engine.shouldQuit()) {
if (needsRedraw) {
- renderSaveGameMenuScreen(_engine, background, loadPalette, 1.0f,
- slotNameFont, slotLabelFont, slotNameFont, slotTitles, activeSlot, statusMessage);
+ renderSaveSlotMenu(menu, &editedTitle);
needsRedraw = false;
}
@@ -1452,59 +1409,24 @@ Common::Error MenuSystem::runLoadGameMenu(const byte *palette, float paletteBrig
if (flow.handleSystemEvent(event, result))
return result;
+ const SaveSlotCommand command = getSaveSlotCommand(event);
+ if (command != kNoSlotCommand) {
+ confirmed = command == kConfirmSlot;
+ return Common::kNoError;
+ }
+
switch (event.type) {
- case Common::EVENT_MOUSEMOVE: {
- const int hoveredSlot = resolveHoveredSlot();
- if (hoveredSlot != -1 && hoveredSlot != activeSlot)
- activeSlot = hoveredSlot;
+ case Common::EVENT_MOUSEMOVE:
needsRedraw = true;
break;
- }
- case Common::EVENT_LBUTTONDOWN: {
- const int hoveredSlot = resolveHoveredSlot();
- statusMessage.clear();
- if (hoveredSlot != -1) {
- activeSlot = hoveredSlot;
- Common::Error loadError = activateSelectedSlot();
- if (loadError.getCode() != Common::kNoError)
- return loadError;
- if (loadedGame)
- return Common::kNoError;
- needsRedraw = true;
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
+ needsRedraw |= deleteTextEntryCharacter(editedTitle);
break;
}
- if (saveConfirmRect().contains(_mousePos)) {
- Common::Error loadError = activateSelectedSlot();
- if (loadError.getCode() != Common::kNoError)
- return loadError;
- if (loadedGame)
- return Common::kNoError;
- } else if (saveCancelRect().contains(_mousePos)) {
- return Common::kNoError;
- }
- needsRedraw = true;
- break;
- }
- case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
- return Common::kNoError;
- if (event.kbd.keycode == Common::KEYCODE_UP) {
- activeSlot = (activeSlot + kSaveSlotCount - 1) % kSaveSlotCount;
- statusMessage.clear();
- needsRedraw = true;
- } else if (event.kbd.keycode == Common::KEYCODE_DOWN) {
- activeSlot = (activeSlot + 1) % kSaveSlotCount;
- statusMessage.clear();
- needsRedraw = true;
- } else if (event.kbd.keycode == Common::KEYCODE_RETURN ||
- event.kbd.keycode == Common::KEYCODE_KP_ENTER) {
- statusMessage.clear();
- Common::Error loadError = activateSelectedSlot();
- if (loadError.getCode() != Common::kNoError)
- return loadError;
- if (loadedGame)
- return Common::kNoError;
- needsRedraw = true;
+ if (event.kbd.ascii >= 32 && event.kbd.ascii <= 126 && event.kbd.ascii != '~') {
+ needsRedraw |= appendTextEntryCharacter(editedTitle, menu.slotNameFont,
+ event.kbd.ascii, kSaveSlotMaxCharacters, kSaveSlotTextWidth);
}
break;
default:
@@ -1522,154 +1444,89 @@ Common::Error MenuSystem::runLoadGameMenu(const byte *palette, float paletteBrig
return Common::kNoError;
}
+void MenuSystem::loadSelectedSlot(SaveSlotMenu &menu, bool &loaded) {
+ if (menu.slotTitles[menu.activeSlot].empty())
+ return;
+
+ Common::Error loadError = _engine.loadGameState(menu.activeSlot);
+ if (loadError.getCode() == Common::kNoError) {
+ loaded = true;
+ return;
+ }
+
+ menu.statusMessage = loadError.getDesc();
+ menu.needsRedraw = true;
+}
+
+Common::Error MenuSystem::saveSelectedSlot(SaveSlotMenu &menu, Flow &flow, bool &saved) {
+ saved = false;
+ Common::String editedTitle = menu.slotTitles[menu.activeSlot];
+ bool confirmed = false;
+ Common::Error entryError = runSaveSlotEditor(menu, flow, editedTitle, confirmed);
+ if (entryError.getCode() != Common::kNoError)
+ return entryError;
+ if (!confirmed)
+ return Common::kNoError;
+
+ Common::Error saveError = _engine.saveGameState(menu.activeSlot, editedTitle);
+ if (saveError.getCode() == Common::kNoError) {
+ saved = true;
+ return Common::kNoError;
+ }
+
+ menu.statusMessage = saveError.getDesc();
+ reloadSaveSlotTitles(menu);
+ menu.needsRedraw = true;
+ return Common::kNoError;
+}
+
+Common::Error MenuSystem::runLoadGameMenu(const byte *palette, float paletteBrightness,
+ Flow &flow, bool &loadedGame) {
+ return runSaveSlotMenu(flow, kLoadMode, loadedGame);
+}
+
Common::Error MenuSystem::runSaveGameMenu(const byte *palette, float paletteBrightness,
Flow &flow, bool &savedGame) {
- (void)palette;
- (void)paletteBrightness;
- savedGame = false;
+ return runSaveSlotMenu(flow, kSaveMode, savedGame);
+}
+
+Common::Error MenuSystem::runSaveSlotMenu(Flow &flow, SaveLoadMode mode, bool &completed) {
+ completed = false;
ResourceManager *resources = _engine.getResources();
MetaEngine *metaEngine = _engine.getMetaEngine();
const CftFontResource *slotNameFontResource = findStartupFontByName(_engine, "MEDFONT1");
const CftFontResource *slotLabelFontResource = findStartupFontByName(_engine, "MEDFONT2");
if (!resources || !metaEngine || !slotNameFontResource || !slotLabelFontResource)
return Common::kReadingFailed;
- if (!_engine.canSaveGameStateCurrently())
+ if (mode == kSaveMode ? !_engine.canSaveGameStateCurrently() : !_engine.canLoadGameStateCurrently())
return Common::kNoError;
- HarvesterCftFont slotNameFont(*slotNameFontResource);
- HarvesterCftFont slotLabelFont(*slotLabelFontResource);
- if (!slotNameFont.isValid() || !slotLabelFont.isValid())
+ SaveSlotMenu menu(*metaEngine, *slotNameFontResource, *slotLabelFontResource);
+ if (!menu.slotNameFont.isValid() || !menu.slotLabelFont.isValid())
return Common::kReadingFailed;
- IndexedBitmap background;
- byte savePalette[256 * 3];
- if (!loadBitmapResource(*resources, kSaveGameBitmapPath, background) ||
- !loadPaletteResource(*resources, kSaveGamePalettePath, savePalette)) {
+ if (!loadBitmapResource(*resources, mode == kSaveMode ? kSaveGameBitmapPath : kLoadGameBitmapPath, menu.background) ||
+ !loadPaletteResource(*resources, mode == kSaveMode ? kSaveGamePalettePath : kLoadGamePalettePath, menu.palette)) {
return Common::kReadingFailed;
}
- Common::Array<Common::String> slotTitles;
- slotTitles.resize(kSaveSlotCount);
- auto reloadSlotTitles = [&]() {
- for (int i = 0; i < kSaveSlotCount; ++i)
- slotTitles[i].clear();
-
- const SaveStateList saves = metaEngine->listSaves(ConfMan.getActiveDomainName().c_str());
- for (const SaveStateDescriptor &save : saves) {
- const int slot = save.getSaveSlot();
- if (slot < 0 || slot >= kSaveSlotCount)
- continue;
- slotTitles[slot] = save.getDescription();
- }
- };
- reloadSlotTitles();
-
- auto resolveHoveredSlot = [&]() -> int {
+ reloadSaveSlotTitles(menu);
+ if (mode == kLoadMode) {
for (int slot = 0; slot < kSaveSlotCount; ++slot) {
- if (saveSlotRect(slot).contains(_mousePos))
- return slot;
- }
- return -1;
- };
- auto runInlineSlotEditor = [&](int slotIndex, Common::String &editedTitle,
- bool &confirmed) -> Common::Error {
- confirmed = false;
- bool needsRedraw = true;
- flow.resetCursorAnimationSequence();
- Graphics::FrameLimiter entryLimiter(g_system, 60);
-
- while (!_engine.shouldQuit()) {
- if (needsRedraw) {
- renderSaveGameMenuScreen(_engine, background, savePalette, 1.0f,
- slotNameFont, slotLabelFont, slotNameFont, slotTitles, slotIndex,
- Common::String(), slotIndex, &editedTitle);
- needsRedraw = false;
- }
-
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event)) {
- Common::Error result = Common::kNoError;
- if (flow.handleSystemEvent(event, result))
- return result;
-
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- needsRedraw = true;
- break;
- case Common::EVENT_LBUTTONDOWN:
- if (saveConfirmRect().contains(_mousePos)) {
- confirmed = true;
- return Common::kNoError;
- }
- if (saveCancelRect().contains(_mousePos))
- return Common::kNoError;
- break;
- case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
- return Common::kNoError;
- if (event.kbd.keycode == Common::KEYCODE_RETURN ||
- event.kbd.keycode == Common::KEYCODE_KP_ENTER) {
- confirmed = true;
- return Common::kNoError;
- }
- if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
- if (!editedTitle.empty()) {
- editedTitle.deleteLastChar();
- needsRedraw = true;
- }
- break;
- }
- if (appendInlineSaveCharacter(editedTitle, slotNameFont, event.kbd.ascii))
- needsRedraw = true;
- break;
- default:
- break;
- }
+ if (!menu.slotTitles[slot].empty()) {
+ menu.activeSlot = slot;
+ break;
}
-
- if (EntityManager *entityManager = _engine.getRuntimeEntities())
- (void)entityManager->syncCursorEntityPosition(_mousePos);
-
- entryLimiter.delayBeforeSwap();
- entryLimiter.startFrame();
}
+ }
- return Common::kNoError;
- };
-
- int activeSlot = 0;
- Common::String statusMessage;
- bool needsRedraw = true;
flow.resetCursorAnimationSequence();
Graphics::FrameLimiter limiter(g_system, 60);
- auto activateSelectedSlot = [&](bool &saved) -> Common::Error {
- saved = false;
- Common::String editedTitle = slotTitles[activeSlot];
- bool confirmed = false;
- Common::Error entryError = runInlineSlotEditor(activeSlot, editedTitle, confirmed);
- if (entryError.getCode() != Common::kNoError)
- return entryError;
- if (!confirmed)
- return Common::kNoError;
-
- Common::Error saveError = _engine.saveGameState(activeSlot, editedTitle);
- if (saveError.getCode() == Common::kNoError) {
- saved = true;
- return Common::kNoError;
- }
-
- statusMessage = saveError.getDesc();
- reloadSlotTitles();
- needsRedraw = true;
- return Common::kNoError;
- };
-
while (!_engine.shouldQuit()) {
- if (needsRedraw) {
- renderSaveGameMenuScreen(_engine, background, savePalette, 1.0f,
- slotNameFont, slotLabelFont, slotNameFont, slotTitles, activeSlot, statusMessage);
- needsRedraw = false;
+ if (menu.needsRedraw) {
+ renderSaveSlotMenu(menu);
+ menu.needsRedraw = false;
}
Common::Event event;
@@ -1678,71 +1535,64 @@ Common::Error MenuSystem::runSaveGameMenu(const byte *palette, float paletteBrig
if (flow.handleSystemEvent(event, result))
return result;
+ bool activateSlot = false;
+ bool redrawAfterActivation = false;
switch (event.type) {
case Common::EVENT_MOUSEMOVE: {
- const int hoveredSlot = resolveHoveredSlot();
- if (hoveredSlot != -1 && hoveredSlot != activeSlot)
- activeSlot = hoveredSlot;
- needsRedraw = true;
+ const int hoveredSlot = getSaveSlotAt(_mousePos);
+ if (hoveredSlot != -1 && hoveredSlot != menu.activeSlot)
+ menu.activeSlot = hoveredSlot;
+ menu.needsRedraw = true;
break;
}
case Common::EVENT_LBUTTONDOWN: {
- const int hoveredSlot = resolveHoveredSlot();
- bool saved = false;
- statusMessage.clear();
+ const int hoveredSlot = getSaveSlotAt(_mousePos);
+ menu.statusMessage.clear();
if (hoveredSlot != -1) {
- activeSlot = hoveredSlot;
- Common::Error saveError = activateSelectedSlot(saved);
- if (saveError.getCode() != Common::kNoError)
- return saveError;
- if (saved) {
- savedGame = true;
- return Common::kNoError;
- }
- break;
- }
- if (saveConfirmRect().contains(_mousePos)) {
- Common::Error saveError = activateSelectedSlot(saved);
- if (saveError.getCode() != Common::kNoError)
- return saveError;
- if (saved) {
- savedGame = true;
+ menu.activeSlot = hoveredSlot;
+ activateSlot = true;
+ // Cancelling a row-opened save editor does not force a browser redraw.
+ redrawAfterActivation = mode == kLoadMode;
+ } else {
+ const SaveSlotCommand command = getSaveSlotCommand(event);
+ if (command == kCancelSlot)
return Common::kNoError;
- }
- } else if (saveCancelRect().contains(_mousePos)) {
- return Common::kNoError;
+ activateSlot = command == kConfirmSlot;
+ redrawAfterActivation = true;
}
- needsRedraw = true;
break;
}
case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
+ if (getSaveSlotCommand(event) == kCancelSlot)
return Common::kNoError;
- if (event.kbd.keycode == Common::KEYCODE_UP) {
- activeSlot = (activeSlot + kSaveSlotCount - 1) % kSaveSlotCount;
- statusMessage.clear();
- needsRedraw = true;
- } else if (event.kbd.keycode == Common::KEYCODE_DOWN) {
- activeSlot = (activeSlot + 1) % kSaveSlotCount;
- statusMessage.clear();
- needsRedraw = true;
- } else if (event.kbd.keycode == Common::KEYCODE_RETURN ||
- event.kbd.keycode == Common::KEYCODE_KP_ENTER) {
- bool saved = false;
- statusMessage.clear();
- Common::Error saveError = activateSelectedSlot(saved);
- if (saveError.getCode() != Common::kNoError)
- return saveError;
- if (saved) {
- savedGame = true;
- return Common::kNoError;
- }
- needsRedraw = true;
+ if (event.kbd.keycode == Common::KEYCODE_UP || event.kbd.keycode == Common::KEYCODE_DOWN) {
+ const int step = event.kbd.keycode == Common::KEYCODE_UP ? kSaveSlotCount - 1 : 1;
+ menu.activeSlot = (menu.activeSlot + step) % kSaveSlotCount;
+ menu.statusMessage.clear();
+ menu.needsRedraw = true;
+ } else if (getSaveSlotCommand(event) == kConfirmSlot) {
+ menu.statusMessage.clear();
+ activateSlot = true;
+ redrawAfterActivation = true;
}
break;
default:
break;
}
+
+ if (activateSlot) {
+ Common::Error actionError = Common::kNoError;
+ if (mode == kSaveMode)
+ actionError = saveSelectedSlot(menu, flow, completed);
+ else
+ loadSelectedSlot(menu, completed);
+ if (actionError.getCode() != Common::kNoError)
+ return actionError;
+ if (completed)
+ return Common::kNoError;
+ }
+ if (redrawAfterActivation)
+ menu.needsRedraw = true;
}
if (EntityManager *entityManager = _engine.getRuntimeEntities())
@@ -1956,10 +1806,7 @@ Common::Error MenuSystem::runPasswordPrompt(const IndexedBitmap &backdrop, const
}
if (event.kbd.keycode == Common::KEYCODE_BACKSPACE ||
event.kbd.keycode == Common::KEYCODE_LEFT) {
- if (!password.empty()) {
- password.deleteLastChar();
- needsRedraw = true;
- }
+ needsRedraw |= deleteTextEntryCharacter(password);
break;
}
if (event.kbd.keycode == Common::KEYCODE_HOME) {
@@ -1969,9 +1816,9 @@ Common::Error MenuSystem::runPasswordPrompt(const IndexedBitmap &backdrop, const
}
break;
}
- if (appendBoundedTextEntryCharacter(password, entryFont, event.kbd.ascii,
- kPasswordMaxCharacters, kPasswordEntryWidth)) {
- needsRedraw = true;
+ if (event.kbd.ascii >= 32 && event.kbd.ascii <= 126 && event.kbd.ascii != '~') {
+ needsRedraw |= appendTextEntryCharacter(password, entryFont, event.kbd.ascii,
+ kPasswordMaxCharacters, kPasswordEntryWidth);
}
break;
default:
diff --git a/engines/harvester/menu.h b/engines/harvester/menu.h
index 58dd3782ca9..b211ea9e6e3 100644
--- a/engines/harvester/menu.h
+++ b/engines/harvester/menu.h
@@ -32,6 +32,10 @@ namespace Graphics {
class Font;
}
+namespace Common {
+struct Event;
+}
+
namespace Harvester {
class HarvesterEngine;
@@ -96,6 +100,20 @@ public:
Flow &flow, bool &promptCompleted);
private:
+ struct SaveSlotMenu;
+ enum SaveLoadMode { kSaveMode, kLoadMode };
+ enum SaveSlotCommand { kNoSlotCommand, kConfirmSlot, kCancelSlot };
+
+ Common::Error runSaveSlotMenu(Flow &flow, SaveLoadMode mode, bool &completed);
+ void reloadSaveSlotTitles(SaveSlotMenu &menu) const;
+ int getSaveSlotAt(const Common::Point &mousePos) const;
+ SaveSlotCommand getSaveSlotCommand(const Common::Event &event) const;
+ void renderSaveSlotMenu(const SaveSlotMenu &menu, const Common::String *editingText = nullptr) const;
+ Common::Error runSaveSlotEditor(SaveSlotMenu &menu, Flow &flow,
+ Common::String &editedTitle, bool &confirmed);
+ Common::Error saveSelectedSlot(SaveSlotMenu &menu, Flow &flow, bool &saved);
+ void loadSelectedSlot(SaveSlotMenu &menu, bool &loaded);
+
Common::Error runLoadGameMenu(const byte *palette, float paletteBrightness,
Flow &flow, bool &loadedGame);
Common::Error runOptionsMenu(const IndexedBitmap &backdrop, const byte *palette,
Commit: a8a11fd66c22d8fcb5af3487ccd8140f6b6da46a
https://github.com/scummvm/scummvm/commit/a8a11fd66c22d8fcb5af3487ccd8140f6b6da46a
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:06-04:00
Commit Message:
HARVESTER: refactor NPC dialogue handling
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/dialogue.cpp
engines/harvester/dialogue.h
engines/harvester/npc/authority_dialogue.cpp
engines/harvester/npc/authority_dialogue.h
engines/harvester/npc/beggar_dialogue.cpp
engines/harvester/npc/beggar_dialogue.h
engines/harvester/npc/boyle_dialogue.cpp
engines/harvester/npc/boyle_dialogue.h
engines/harvester/npc/buster_dialogue.cpp
engines/harvester/npc/buster_dialogue.h
engines/harvester/npc/butcher_dialogue.cpp
engines/harvester/npc/butcher_dialogue.h
engines/harvester/npc/chessmaster_dialogue.cpp
engines/harvester/npc/chessmaster_dialogue.h
engines/harvester/npc/cloak_atnd_dialogue.cpp
engines/harvester/npc/cloak_atnd_dialogue.h
engines/harvester/npc/curator_dialogue.cpp
engines/harvester/npc/curator_dialogue.h
engines/harvester/npc/dad_dialogue.cpp
engines/harvester/npc/dad_dialogue.h
engines/harvester/npc/dark_woman_dialogue.cpp
engines/harvester/npc/dark_woman_dialogue.h
engines/harvester/npc/dialogue_handler.h
engines/harvester/npc/dialogue_runtime.h
engines/harvester/npc/dwayne_dialogue.cpp
engines/harvester/npc/dwayne_dialogue.h
engines/harvester/npc/edna_dialogue.cpp
engines/harvester/npc/edna_dialogue.h
engines/harvester/npc/fireman1_dialogue.cpp
engines/harvester/npc/fireman1_dialogue.h
engines/harvester/npc/fireman2_dialogue.cpp
engines/harvester/npc/fireman2_dialogue.h
engines/harvester/npc/gladiator_dialogue.cpp
engines/harvester/npc/gladiator_dialogue.h
engines/harvester/npc/hank_dialogue.cpp
engines/harvester/npc/hank_dialogue.h
engines/harvester/npc/herrill_dialogue.cpp
engines/harvester/npc/herrill_dialogue.h
engines/harvester/npc/inquisitor_dialogue.cpp
engines/harvester/npc/inquisitor_dialogue.h
engines/harvester/npc/jimmy_dialogue.cpp
engines/harvester/npc/jimmy_dialogue.h
engines/harvester/npc/johnson_dialogue.cpp
engines/harvester/npc/johnson_dialogue.h
engines/harvester/npc/karin_dialogue.cpp
engines/harvester/npc/karin_dialogue.h
engines/harvester/npc/librarian_dialogue.cpp
engines/harvester/npc/librarian_dialogue.h
engines/harvester/npc/lodge_chef_dialogue.cpp
engines/harvester/npc/lodge_chef_dialogue.h
engines/harvester/npc/loomis_dialogue.cpp
engines/harvester/npc/loomis_dialogue.h
engines/harvester/npc/madam_dialogue.cpp
engines/harvester/npc/madam_dialogue.h
engines/harvester/npc/maint_man_dialogue.cpp
engines/harvester/npc/maint_man_dialogue.h
engines/harvester/npc/mcknight_dialogue.cpp
engines/harvester/npc/mcknight_dialogue.h
engines/harvester/npc/memb_dir_dialogue.cpp
engines/harvester/npc/memb_dir_dialogue.h
engines/harvester/npc/mom_dialogue.cpp
engines/harvester/npc/mom_dialogue.h
engines/harvester/npc/mother_dialogue.cpp
engines/harvester/npc/mother_dialogue.h
engines/harvester/npc/moynahan_dialogue.cpp
engines/harvester/npc/moynahan_dialogue.h
engines/harvester/npc/mr_potts_dialogue.cpp
engines/harvester/npc/mr_potts_dialogue.h
engines/harvester/npc/mrs_potts_dialogue.cpp
engines/harvester/npc/mrs_potts_dialogue.h
engines/harvester/npc/nude_man_dialogue.cpp
engines/harvester/npc/nude_man_dialogue.h
engines/harvester/npc/parsons_dialogue.cpp
engines/harvester/npc/parsons_dialogue.h
engines/harvester/npc/pastorelli_dialogue.cpp
engines/harvester/npc/pastorelli_dialogue.h
engines/harvester/npc/phelps_dialogue.cpp
engines/harvester/npc/phelps_dialogue.h
engines/harvester/npc/priest_dialogue.cpp
engines/harvester/npc/priest_dialogue.h
engines/harvester/npc/pta_mom_dialogue.cpp
engines/harvester/npc/pta_mom_dialogue.h
engines/harvester/npc/ryder_dialogue.cpp
engines/harvester/npc/ryder_dialogue.h
engines/harvester/npc/sergeant_dialogue.cpp
engines/harvester/npc/sergeant_dialogue.h
engines/harvester/npc/sparky_dialogue.cpp
engines/harvester/npc/sparky_dialogue.h
engines/harvester/npc/stephanie_dialogue.cpp
engines/harvester/npc/stephanie_dialogue.h
engines/harvester/npc/stub_dialogue.cpp
engines/harvester/npc/stub_dialogue.h
engines/harvester/npc/swell_dialogue.cpp
engines/harvester/npc/swell_dialogue.h
engines/harvester/npc/valet_dialogue.cpp
engines/harvester/npc/valet_dialogue.h
engines/harvester/npc/vet_dialogue.cpp
engines/harvester/npc/vet_dialogue.h
engines/harvester/npc/wasp_woman_dialogue.cpp
engines/harvester/npc/wasp_woman_dialogue.h
engines/harvester/npc/whaley_dialogue.cpp
engines/harvester/npc/whaley_dialogue.h
diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index 80d29481e48..2626ea93933 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -1338,84 +1338,89 @@ DialogueSystem::DialogueSystem(HarvesterEngine &engine, Common::Point &mousePos)
DialogueSystem::~DialogueSystem() {
for (uint i = 0; i < _npcHandlers.size(); ++i)
- delete _npcHandlers[i];
+ delete _npcHandlers[i].handler;
}
-bool DialogueSystem::hasRoomNpcHandler(const Common::String &npcName) const {
- for (uint i = 0; i < _npcHandlers.size(); ++i) {
- if (_npcHandlers[i]->matchesNpc(npcName))
- return true;
+NpcDialogueHandler *DialogueSystem::findNpcHandler(const Common::String &npcName) const {
+ for (const NpcHandlerRegistration ®istration : _npcHandlers) {
+ for (const char *name : registration.names) {
+ if (npcName.equalsIgnoreCase(name))
+ return registration.handler;
+ }
}
+ return nullptr;
+}
- return false;
+bool DialogueSystem::hasRoomNpcHandler(const Common::String &npcName) const {
+ return findNpcHandler(npcName) != nullptr;
}
void DialogueSystem::registerNpcHandlers() {
- _npcHandlers.push_back(new AuthorityDialogueHandler());
- _npcHandlers.push_back(new BeggarDialogueHandler());
- _npcHandlers.push_back(new BoyleDialogueHandler());
- _npcHandlers.push_back(new BusterDialogueHandler());
- _npcHandlers.push_back(new ButcherDialogueHandler());
- _npcHandlers.push_back(new DwayneDialogueHandler());
- _npcHandlers.push_back(new EdnaDialogueHandler());
- _npcHandlers.push_back(new Fireman1DialogueHandler());
- _npcHandlers.push_back(new Fireman2DialogueHandler());
- _npcHandlers.push_back(new ChessmasterDialogueHandler());
- _npcHandlers.push_back(new CloakAtndDialogueHandler());
- _npcHandlers.push_back(new CuratorDialogueHandler());
- _npcHandlers.push_back(new DadDialogueHandler());
- _npcHandlers.push_back(new DarkWomanDialogueHandler());
- _npcHandlers.push_back(new JimmyDialogueHandler());
- _npcHandlers.push_back(new InquisitorDialogueHandler());
- _npcHandlers.push_back(new KarinDialogueHandler());
- _npcHandlers.push_back(new WaspWomanDialogueHandler());
- _npcHandlers.push_back(new GladiatorDialogueHandler());
- _npcHandlers.push_back(new LibrarianDialogueHandler());
- _npcHandlers.push_back(new LoomisDialogueHandler());
- _npcHandlers.push_back(new McknightDialogueHandler());
- _npcHandlers.push_back(new MembDirDialogueHandler());
- _npcHandlers.push_back(new MaintManDialogueHandler());
- _npcHandlers.push_back(new MadamDialogueHandler());
- _npcHandlers.push_back(new MomDialogueHandler());
- _npcHandlers.push_back(new MotherDialogueHandler());
- _npcHandlers.push_back(new MoynahanDialogueHandler());
- _npcHandlers.push_back(new MrPottsDialogueHandler());
- _npcHandlers.push_back(new MrsPottsDialogueHandler());
- _npcHandlers.push_back(new LodgeChefDialogueHandler());
- _npcHandlers.push_back(new NudeManDialogueHandler());
- _npcHandlers.push_back(new ParsonsDialogueHandler());
- _npcHandlers.push_back(new PastorelliDialogueHandler());
- _npcHandlers.push_back(new PhelpsDialogueHandler());
- _npcHandlers.push_back(new PriestDialogueHandler());
- _npcHandlers.push_back(new RyderDialogueHandler());
- _npcHandlers.push_back(new ValetDialogueHandler());
- _npcHandlers.push_back(new VetDialogueHandler());
- _npcHandlers.push_back(new SparkyDialogueHandler());
- _npcHandlers.push_back(new StephanieDialogueHandler());
- _npcHandlers.push_back(new SwellDialogueHandler());
- _npcHandlers.push_back(new WhaleyDialogueHandler());
- _npcHandlers.push_back(new HankDialogueHandler());
- _npcHandlers.push_back(new HerrillDialogueHandler());
- _npcHandlers.push_back(new JohnsonDialogueHandler());
- _npcHandlers.push_back(new PtaMomDialogueHandler());
-
- _npcHandlers.push_back(new SergeantDialogueHandler());
- _npcHandlers.push_back(new StubNpcDialogueHandler("PTA_MOM"));
+ _npcHandlers.push_back({ new AuthorityDialogueHandler(), { "AUTHORITY", "AUTHORITY2" } });
+ _npcHandlers.push_back({ new BeggarDialogueHandler(), { "BEGGAR" } });
+ _npcHandlers.push_back({ new BoyleDialogueHandler(), { "BOYLE" } });
+ _npcHandlers.push_back({ new BusterDialogueHandler(), { "BUSTER" } });
+ _npcHandlers.push_back({ new ButcherDialogueHandler(), { "BUTCHER" } });
+ _npcHandlers.push_back({ new DwayneDialogueHandler(), { "DWAYNE", "DWAYNE_DNALFT", "DWAYNE_ST_BEDRM" } });
+ _npcHandlers.push_back({ new EdnaDialogueHandler(), { "EDNA" } });
+ _npcHandlers.push_back({ new Fireman1DialogueHandler(), { "FIREMAN1" } });
+ _npcHandlers.push_back({ new Fireman2DialogueHandler(), { "FIREMAN2" } });
+ _npcHandlers.push_back({ new ChessmasterDialogueHandler(), { "CHESSMASTER" } });
+ _npcHandlers.push_back({ new CloakAtndDialogueHandler(), { "CLOAK_ATND" } });
+ _npcHandlers.push_back({ new CuratorDialogueHandler(), { "CURATOR" } });
+ _npcHandlers.push_back({ new DadDialogueHandler(), { "DAD" } });
+ _npcHandlers.push_back({ new DarkWomanDialogueHandler(), { "DARK_WOMAN" } });
+ _npcHandlers.push_back({ new JimmyDialogueHandler(), { "JIMMY" } });
+ _npcHandlers.push_back({ new InquisitorDialogueHandler(), { "INQUISITOR" } });
+ _npcHandlers.push_back({ new KarinDialogueHandler(), { "KARIN", "KARIN_STANDING", "KARIN_CEM10", "KARIN_OFFICE" } });
+ _npcHandlers.push_back({ new WaspWomanDialogueHandler(), { "WASP_WOMAN" } });
+ _npcHandlers.push_back({ new GladiatorDialogueHandler(), { "GLADIATOR" } });
+ _npcHandlers.push_back({ new LibrarianDialogueHandler(), { "LIBRARIAN" } });
+ _npcHandlers.push_back({ new LoomisDialogueHandler(), { "LOOMIS" } });
+ _npcHandlers.push_back({ new McknightDialogueHandler(), { "MCKNIGHT" } });
+ _npcHandlers.push_back({ new MembDirDialogueHandler(), { "MEMB_DIR" } });
+ _npcHandlers.push_back({ new MaintManDialogueHandler(), { "MAINT_MAN" } });
+ _npcHandlers.push_back({ new MadamDialogueHandler(), { "MADAM" } });
+ _npcHandlers.push_back({ new MomDialogueHandler(), { "MOM" } });
+ _npcHandlers.push_back({ new MotherDialogueHandler(), { "MOTHER" } });
+ _npcHandlers.push_back({ new MoynahanDialogueHandler(), { "MOYNAHAN", "MOYNAHAN_MBLM" } });
+ _npcHandlers.push_back({ new MrPottsDialogueHandler(), { "MR_POTTS", "POTTS_FLESH", "MR_POTTS_CEM10", "MR_POTTS_HALL" } });
+ _npcHandlers.push_back({ new MrsPottsDialogueHandler(), { "MRS_POTTS", "MRS_POTTS_ST_BEDRM" } });
+ _npcHandlers.push_back({ new LodgeChefDialogueHandler(), { "LODGE_CHEF" } });
+ _npcHandlers.push_back({ new NudeManDialogueHandler(), { "NUDE_MAN" } });
+ _npcHandlers.push_back({ new ParsonsDialogueHandler(), { "PARSONS" } });
+ _npcHandlers.push_back({ new PastorelliDialogueHandler(), { "PASTORELLI" } });
+ _npcHandlers.push_back({ new PhelpsDialogueHandler(), { "PHELPS" } });
+ _npcHandlers.push_back({ new PriestDialogueHandler(), { "PRIEST" } });
+ _npcHandlers.push_back({ new RyderDialogueHandler(), { "RYDER", "RYDER_TV_OUT" } });
+ _npcHandlers.push_back({ new ValetDialogueHandler(), { "VALET" } });
+ _npcHandlers.push_back({ new VetDialogueHandler(), { "VET" } });
+ _npcHandlers.push_back({ new SparkyDialogueHandler(), { "SPARKY" } });
+ _npcHandlers.push_back({ new StephanieDialogueHandler(), { "STEPHANIE" } });
+ _npcHandlers.push_back({ new SwellDialogueHandler(), { "SWELL" } });
+ _npcHandlers.push_back({ new WhaleyDialogueHandler(), { "WHALEY" } });
+ _npcHandlers.push_back({ new HankDialogueHandler(), { "HANK" } });
+ _npcHandlers.push_back({ new HerrillDialogueHandler(), { "HERRILL", "HERRILL_LOG" } });
+ _npcHandlers.push_back({ new JohnsonDialogueHandler(), { "JOHNSON" } });
+ _npcHandlers.push_back({ new PtaMomDialogueHandler(), { "PTA_MOM1", "PTA_MOM2", "PTA_MOM3", "PTA_MOM4", "PTA_MOM5" } });
+
+ _npcHandlers.push_back({ new SergeantDialogueHandler(), { "SERGEANT" } });
+ _npcHandlers.push_back({ new StubNpcDialogueHandler("PTA_MOM"), { "PTA_MOM" } });
}
void DialogueSystem::resetRoomNpcDialogueState() {
_sharedDialogueState = DialogueSharedState();
for (uint i = 0; i < _npcHandlers.size(); ++i)
- _npcHandlers[i]->resetState();
+ _npcHandlers[i].handler->resetState();
}
void DialogueSystem::syncRuntimeSaveState(Common::Serializer &s) {
syncDialogueSharedState(s, _sharedDialogueState);
for (uint i = 0; i < _npcHandlers.size(); ++i)
- _npcHandlers[i]->syncState(s);
+ _npcHandlers[i].handler->syncState(s);
if (s.isLoading()) {
for (uint i = 0; i < _npcHandlers.size(); ++i)
- _npcHandlers[i]->migrateSharedState(_sharedDialogueState);
+ _npcHandlers[i].handler->migrateSharedState(_sharedDialogueState);
}
}
@@ -1427,7 +1432,8 @@ Common::Error DialogueSystem::runRoomNpcDialogue(const IndexedBitmap &backdrop,
Text *text = _engine.getText();
if (!script || !text || !backdrop.isValid())
return Common::kReadingFailed;
- if (!hasRoomNpcHandler(npc.npcName)) {
+ NpcDialogueHandler *handler = findNpcHandler(npc.npcName);
+ if (!handler) {
debugC(1, kDebugDialogue,
"Harvester: blocked room NPC dialogue npc='%s' reason='no handler'",
npc.npcName.c_str());
@@ -1453,13 +1459,7 @@ Common::Error DialogueSystem::runRoomNpcDialogue(const IndexedBitmap &backdrop,
DialogueRuntime runtime(
_engine, *script, *text, flow, currentRoomName, session.getGenericByeTopic(), session);
- for (uint i = 0; i < _npcHandlers.size(); ++i) {
- if (_npcHandlers[i]->matchesNpc(npc.npcName))
- return _npcHandlers[i]->handleDialogue(runtime, usedItemName, _sharedDialogueState);
- }
-
- debug(1, "Harvester: unsupported room NPC dialogue handler '%s'", npc.npcName.c_str());
- return Common::kNoError;
+ return handler->handleDialogue(runtime, usedItemName, _sharedDialogueState);
}
} // End of namespace Harvester
diff --git a/engines/harvester/dialogue.h b/engines/harvester/dialogue.h
index 4fe59c95ea8..d006caedf21 100644
--- a/engines/harvester/dialogue.h
+++ b/engines/harvester/dialogue.h
@@ -55,12 +55,18 @@ public:
Flow &flow);
private:
+ struct NpcHandlerRegistration {
+ NpcDialogueHandler *handler;
+ Common::Array<const char *> names;
+ };
+
void registerNpcHandlers();
+ NpcDialogueHandler *findNpcHandler(const Common::String &npcName) const;
HarvesterEngine &_engine;
Common::Point &_mousePos;
DialogueSharedState _sharedDialogueState;
- Common::Array<NpcDialogueHandler *> _npcHandlers;
+ Common::Array<NpcHandlerRegistration> _npcHandlers;
};
} // End of namespace Harvester
diff --git a/engines/harvester/npc/authority_dialogue.cpp b/engines/harvester/npc/authority_dialogue.cpp
index 075dd31aaa0..089a313b85c 100644
--- a/engines/harvester/npc/authority_dialogue.cpp
+++ b/engines/harvester/npc/authority_dialogue.cpp
@@ -26,30 +26,18 @@
namespace Harvester {
-namespace {
-
-static const char *const kAuthorityNpc = "AUTHORITY";
-static const char *const kAuthority2Npc = "AUTHORITY2";
-
-} // End of namespace
-
-bool AuthorityDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kAuthorityNpc) ||
- npcName.equalsIgnoreCase(kAuthority2Npc);
-}
-
Common::Error AuthorityDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
if (runtime.startupScript().getFlagValue("STOP_AUTHOR_TALK"))
return Common::kNoError;
if (runtime.startupScript().getFlagValue("IF_DON_T_EAT_THE_FOOD")) {
- Common::Error lineError = runtime.playDialogueLine(0x3992, kAuthorityNpc);
+ Common::Error lineError = runtime.playDialogueLine(0x3992, "AUTHORITY");
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getFlagValue("IF_YOU_EAT_THE_FOOD_AND_DEFEAT_THE_ENEMIES"))
- return runtime.playDialogueLine(0x399b, kAuthorityNpc);
+ return runtime.playDialogueLine(0x399b, "AUTHORITY");
return Common::kNoError;
}
@@ -58,7 +46,7 @@ Common::Error AuthorityDialogueHandler::handleDialogue(DialogueRuntime &runtime,
runtime.startupScript().getFlagValue("IF_YOU_EAT_THE_FOOD_AND_DEFEAT_THE_ENEMIES")
? 0x399b
: 0x398a,
- kAuthorityNpc);
+ "AUTHORITY");
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/authority_dialogue.h b/engines/harvester/npc/authority_dialogue.h
index 771441ef3f1..b123e73a7c7 100644
--- a/engines/harvester/npc/authority_dialogue.h
+++ b/engines/harvester/npc/authority_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class AuthorityDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/beggar_dialogue.cpp b/engines/harvester/npc/beggar_dialogue.cpp
index 05f7de92c01..4276623c57f 100644
--- a/engines/harvester/npc/beggar_dialogue.cpp
+++ b/engines/harvester/npc/beggar_dialogue.cpp
@@ -28,8 +28,6 @@ namespace Harvester {
namespace {
-static const char *const kBeggarNpc = "BEGGAR";
-static const char *const kPcSpeaker = "PC";
static const char *const kBeggarInterruptFlag = "BEGGAR_INTERRUPT_CONVERSATION";
static const char *const kBeggarDialog3ActionTag = "BEGGAR_DIALOG_3";
static const int kBeggarInitialResponseLine = 0x0;
@@ -37,21 +35,11 @@ static const int kBeggarFollowupResponseLine = 0x1;
} // End of namespace
-bool BeggarDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kBeggarNpc);
-}
-
Common::Error BeggarDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
- auto playBeggarLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kBeggarNpc, headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kPcSpeaker, headVariant);
- };
auto queueBeggarMonsterfyTransition = [&]() {
InteractionResult interaction;
- if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy(kBeggarNpc)) {
+ if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy("BEGGAR")) {
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
}
@@ -67,15 +55,15 @@ Common::Error BeggarDialogueHandler::handleDialogue(DialogueRuntime &runtime,
runtime.queueDialogueInteractionIfNeeded(interaction);
}
- Common::Error lineError = playBeggarLine(0x1276, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1276, "BEGGAR", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x127a, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x127a, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBeggarLine(0x127e);
+ lineError = runtime.playDialogueLineWithVariant(0x127e, "BEGGAR", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -86,9 +74,9 @@ Common::Error BeggarDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playBeggarLine(0x128d, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x128d, "BEGGAR", 1);
} else if (responseIndex == 2) {
- lineError = playBeggarLine(0x1291, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x1291, "BEGGAR", 3);
} else {
queueBeggarMonsterfyTransition();
return Common::kNoError;
@@ -96,7 +84,7 @@ Common::Error BeggarDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBeggarLine(0x1295);
+ lineError = runtime.playDialogueLineWithVariant(0x1295, "BEGGAR", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -107,11 +95,11 @@ Common::Error BeggarDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playBeggarLine(0x12ab, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x12ab, "BEGGAR", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playBeggarLine(0x12a5, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x12a5, "BEGGAR", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/beggar_dialogue.h b/engines/harvester/npc/beggar_dialogue.h
index d16aad1e47b..8653f159c83 100644
--- a/engines/harvester/npc/beggar_dialogue.h
+++ b/engines/harvester/npc/beggar_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class BeggarDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/boyle_dialogue.cpp b/engines/harvester/npc/boyle_dialogue.cpp
index 5f6946ad439..d146d94e034 100644
--- a/engines/harvester/npc/boyle_dialogue.cpp
+++ b/engines/harvester/npc/boyle_dialogue.cpp
@@ -29,8 +29,6 @@ namespace Harvester {
namespace {
-static const char *const kBoyleNpc = "BOYLE";
-static const char *const kPcSpeaker = "PC";
static const char *const kInventoryOwnerName = "INVENTORY";
static const char *const kBoylesButtonObject = "BOYLES_BUTTON";
static const char *const kGascanObject = "GASCAN";
@@ -41,88 +39,88 @@ static const char *const kBoyleArsonistTopic = "Arsonist";
static const char *const kDialogueC019BFstPath = "GRAPHIC/FST/C019B.FST";
static const DialogueLineEntry kBoyleHaveLodgeAppEvidenceLines[] = {
- { 0x13d, kBoyleNpc, 2 },
- { 0x141, kPcSpeaker, 0 },
- { 0x145, kBoyleNpc, 2 },
- { 0x14a, kPcSpeaker, 0 },
- { 0x14e, kBoyleNpc, 3 }
+ { 0x13d, "BOYLE", 2 },
+ { 0x141, "PC", 0 },
+ { 0x145, "BOYLE", 2 },
+ { 0x14a, "PC", 0 },
+ { 0x14e, "BOYLE", 3 }
};
static const DialogueLineEntry kBoyleButtonIntroLines[] = {
- { 0x155, kBoyleNpc, 1 },
- { 0x15a, kPcSpeaker, 0 },
- { 0x15f, kBoyleNpc, 2 }
+ { 0x155, "BOYLE", 1 },
+ { 0x15a, "PC", 0 },
+ { 0x15f, "BOYLE", 2 }
};
static const DialogueLineEntry kBoyleButtonResponse2Lines[] = {
- { 0x174, kBoyleNpc, 0 },
- { 0x179, kPcSpeaker, 0 },
- { 0x17d, kBoyleNpc, 0 }
+ { 0x174, "BOYLE", 0 },
+ { 0x179, "PC", 0 },
+ { 0x17d, "BOYLE", 0 }
};
static const DialogueLineEntry kBoyleNoteResponse1IntroLines[] = {
- { 0x1a1, kBoyleNpc, 2 },
- { 0x1a9, kPcSpeaker, 0 },
- { 0x1ad, kBoyleNpc, 0 }
+ { 0x1a1, "BOYLE", 2 },
+ { 0x1a9, "PC", 0 },
+ { 0x1ad, "BOYLE", 0 }
};
static const DialogueLineEntry kBoyleGascanRewardLines[] = {
- { 0x1f2, kBoyleNpc, 3 },
- { 0x1f6, kPcSpeaker, 2 },
- { 0x1fa, kBoyleNpc, 3 },
- { 0x202, kPcSpeaker, 2 },
- { 0x206, kBoyleNpc, 2 }
+ { 0x1f2, "BOYLE", 3 },
+ { 0x1f6, "PC", 2 },
+ { 0x1fa, "BOYLE", 3 },
+ { 0x202, "PC", 2 },
+ { 0x206, "BOYLE", 2 }
};
static const DialogueLineEntry kBoyleIntroOpeningLines[] = {
- { 0x7, kBoyleNpc, 0 },
- { 0xb, kPcSpeaker, 0 },
- { 0xf, kBoyleNpc, 1 }
+ { 0x7, "BOYLE", 0 },
+ { 0xb, "PC", 0 },
+ { 0xf, "BOYLE", 1 }
};
static const DialogueLineEntry kBoyleIntroResponse1Lines[] = {
- { 0x19, kBoyleNpc, 0 },
- { 0x1d, kPcSpeaker, 2 },
- { 0x21, kBoyleNpc, 1 }
+ { 0x19, "BOYLE", 0 },
+ { 0x1d, "PC", 2 },
+ { 0x21, "BOYLE", 1 }
};
static const DialogueLineEntry kBoyleIntroResponse1TailLines[] = {
- { 0x3a, kBoyleNpc, 0 },
- { 0x41, kPcSpeaker, 2 },
- { 0x45, kBoyleNpc, 0 }
+ { 0x3a, "BOYLE", 0 },
+ { 0x41, "PC", 2 },
+ { 0x45, "BOYLE", 0 }
};
static const DialogueLineEntry kBoyleIntroResponse2Choice2Lines[] = {
- { 0x76, kBoyleNpc, 0 },
- { 0x77, kBoyleNpc, 2 }
+ { 0x76, "BOYLE", 0 },
+ { 0x77, "BOYLE", 2 }
};
static const DialogueLineEntry kBoyleKeywordTopic0eLines[] = {
- { 0x8c, kPcSpeaker, 0 },
- { 0x90, kBoyleNpc, 0 },
- { 0x94, kPcSpeaker, 0 },
- { 0x98, kBoyleNpc, 0 },
- { 0x9d, kPcSpeaker, 0 },
- { 0xa1, kBoyleNpc, 1 }
+ { 0x8c, "PC", 0 },
+ { 0x90, "BOYLE", 0 },
+ { 0x94, "PC", 0 },
+ { 0x98, "BOYLE", 0 },
+ { 0x9d, "PC", 0 },
+ { 0xa1, "BOYLE", 1 }
};
static const DialogueLineEntry kBoyleKeywordTopic17Lines[] = {
- { 0xee, kPcSpeaker, 0 },
- { 0xf2, kBoyleNpc, 2 },
- { 0xf6, kPcSpeaker, 4 },
- { 0xfa, kBoyleNpc, 0 }
+ { 0xee, "PC", 0 },
+ { 0xf2, "BOYLE", 2 },
+ { 0xf6, "PC", 4 },
+ { 0xfa, "BOYLE", 0 }
};
static const DialogueLineEntry kBoyleKeywordArsonResponse1Lines[] = {
- { 0x126, kBoyleNpc, 0 },
- { 0x12c, kPcSpeaker, 0 },
- { 0x130, kBoyleNpc, 2 }
+ { 0x126, "BOYLE", 0 },
+ { 0x12c, "PC", 0 },
+ { 0x130, "BOYLE", 2 }
};
static const DialogueLineEntry kBoyleFollowupBurnedTvLines[] = {
- { 0x28a, kBoyleNpc, 1 },
- { 0x28e, kPcSpeaker, 0 },
- { 0x292, kBoyleNpc, 1 }
+ { 0x28a, "BOYLE", 1 },
+ { 0x28e, "PC", 0 },
+ { 0x292, "BOYLE", 1 }
};
static const int kBoyleKeywordTopic0fTo12Lines[] = { 0xf, 0x10, 0x11, 0x12 };
@@ -132,33 +130,14 @@ static const int kBoyleKeywordTopic18To1bLines[] = { 0x18, 0x19, 0x1a, 0x1b };
} // End of namespace
-bool BoyleDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kBoyleNpc);
-}
-
Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
BoyleRoomDialogueState &state = _state;
Common::String boyleTopicBuffer;
int boyleTopicBufferLineIndex = -1;
- auto assignBoyleTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(boyleTopicBuffer, boyleTopicBufferLineIndex,
- responseLineIndex, "Boyle topic buffer");
- };
- auto clearBoyleTopicBuffer = [&]() {
- boyleTopicBuffer.clear();
- boyleTopicBufferLineIndex = -1;
- };
- auto playLine = [&](int wavId, const char *speakerId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, speakerId, headVariant);
- };
- auto playBoyleLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return playLine(wavId, kBoyleNpc, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+ DialogueTopicBuffer topics(runtime, boyleTopicBuffer, boyleTopicBufferLineIndex, "Boyle topic buffer");
+
auto hideInventoryItem = [&](const char *objectName) {
return runtime.startupScript().setRuntimeObjectVisible(
kInventoryOwnerName, objectName, false);
@@ -184,7 +163,7 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!usedItemName.empty()) {
if (usedItemName.equalsIgnoreCase(kBoylesButtonObject)) {
- lineError = playSequence(kBoyleButtonIntroLines, ARRAYSIZE(kBoyleButtonIntroLines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleButtonIntroLines, ARRAYSIZE(kBoyleButtonIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -194,26 +173,25 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playBoyleLine(0x16d, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x16d, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playBoyleLine(0x100, 1);
+ return runtime.playDialogueLineWithVariant(0x100, "BOYLE", 1);
}
if (responseIndex == 2) {
- lineError = playSequence(kBoyleButtonResponse2Lines,
- ARRAYSIZE(kBoyleButtonResponse2Lines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleButtonResponse2Lines, ARRAYSIZE(kBoyleButtonResponse2Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (state.extraEvidenceReplyEnabled) {
- lineError = playLine(0x186, kPcSpeaker, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x186, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBoyleLine(0x18b);
+ lineError = runtime.playDialogueLineWithVariant(0x18b, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else {
- lineError = playBoyleLine(0x1d2);
+ lineError = runtime.playDialogueLineWithVariant(0x1d2, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -229,11 +207,11 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (isBlackmailEvidence(usedItemName)) {
if (runtime.startupScript().getFlagValue(kHaveLodgeAppFlag)) {
- return playSequence(kBoyleHaveLodgeAppEvidenceLines,
+ return runtime.playDialogueEntrySequence(kBoyleHaveLodgeAppEvidenceLines,
ARRAYSIZE(kBoyleHaveLodgeAppEvidenceLines));
}
- lineError = playBoyleLine(0x197);
+ lineError = runtime.playDialogueLineWithVariant(0x197, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -244,22 +222,22 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 1) {
sharedState.boyleGascanApplicationState = true;
- lineError = playSequence(kBoyleNoteResponse1IntroLines,
+ lineError = runtime.playDialogueEntrySequence(kBoyleNoteResponse1IntroLines,
ARRAYSIZE(kBoyleNoteResponse1IntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (state.extraEvidenceReplyEnabled) {
- lineError = playLine(0x186, kPcSpeaker, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x186, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBoyleLine(0x1b8);
+ lineError = runtime.playDialogueLineWithVariant(0x1b8, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- return playBoyleLine(0x1d2);
+ return runtime.playDialogueLineWithVariant(0x1d2, "BOYLE", 0);
}
if (responseIndex == 2) {
- lineError = playBoyleLine(0x1d9, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1d9, "BOYLE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -269,17 +247,16 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (followupResponseIndex == 1)
- return playBoyleLine(0x1e5, 1);
+ return runtime.playDialogueLineWithVariant(0x1e5, "BOYLE", 1);
if (followupResponseIndex == 2)
- return playBoyleLine(0x1ea, 2);
+ return runtime.playDialogueLineWithVariant(0x1ea, "BOYLE", 2);
}
return Common::kNoError;
}
if (usedItemName.equalsIgnoreCase(kGascanObject) &&
sharedState.boyleGascanApplicationState) {
- lineError = playSequence(kBoyleGascanRewardLines,
- ARRAYSIZE(kBoyleGascanRewardLines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleGascanRewardLines, ARRAYSIZE(kBoyleGascanRewardLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -291,30 +268,30 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
- return playBoyleLine(0x25f, 2);
+ return runtime.playDialogueLineWithVariant(0x25f, "BOYLE", 2);
}
if (usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
sharedState.discussedCasketPhotoEvidence = 1;
- lineError = playBoyleLine(0x24f, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x24f, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2ebc) {
- lineError = playLine(0x253, kPcSpeaker, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x253, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- return playBoyleLine(0x258, 2);
+ return runtime.playDialogueLineWithVariant(0x258, "BOYLE", 2);
}
- return playBoyleLine(0x249);
+ return runtime.playDialogueLineWithVariant(0x249, "BOYLE", 0);
}
if (state.introPending) {
state.introPending = false;
- lineError = playSequence(kBoyleIntroOpeningLines, ARRAYSIZE(kBoyleIntroOpeningLines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleIntroOpeningLines, ARRAYSIZE(kBoyleIntroOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -325,8 +302,7 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
bool seedButtonTopicBuffer = false;
if (responseIndex == 1) {
- lineError = playSequence(kBoyleIntroResponse1Lines,
- ARRAYSIZE(kBoyleIntroResponse1Lines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleIntroResponse1Lines, ARRAYSIZE(kBoyleIntroResponse1Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -336,22 +312,22 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (followupResponseIndex == 1) {
- lineError = playBoyleLine(0x2f);
+ lineError = runtime.playDialogueLineWithVariant(0x2f, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (followupResponseIndex == 2) {
- lineError = playBoyleLine(0x34, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x34, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playSequence(kBoyleIntroResponse1TailLines,
+ lineError = runtime.playDialogueEntrySequence(kBoyleIntroResponse1TailLines,
ARRAYSIZE(kBoyleIntroResponse1TailLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
seedButtonTopicBuffer = true;
} else if (responseIndex == 2) {
- lineError = playBoyleLine(0x4d, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x4d, "BOYLE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -361,7 +337,7 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (followupResponseIndex == 1) {
- lineError = playBoyleLine(0x59, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x59, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -371,59 +347,59 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (nestedResponseIndex == 1) {
- lineError = playBoyleLine(0x68, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x68, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (nestedResponseIndex == 2) {
- lineError = playBoyleLine(0x6c, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x6c, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else if (followupResponseIndex == 2) {
state.extraEvidenceReplyEnabled = true;
- lineError = playSequence(kBoyleIntroResponse2Choice2Lines,
+ lineError = runtime.playDialogueEntrySequence(kBoyleIntroResponse2Choice2Lines,
ARRAYSIZE(kBoyleIntroResponse2Choice2Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playBoyleLine(0x80, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x80, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBoyleTopicBuffer(0x9);
+ topics.assign(0x9);
seedButtonTopicBuffer = true;
}
if (seedButtonTopicBuffer && hasBoylesButton)
- assignBoyleTopicBuffer(0xa);
+ topics.assign(0xa);
} else {
- lineError = playBoyleLine(0x23c);
+ lineError = runtime.playDialogueLineWithVariant(0x23c, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (hasBoylesButton)
- assignBoyleTopicBuffer(0xb);
+ topics.assign(0xb);
}
if ((sharedState.discussedNoteCheckbookEvidence != 0 ||
sharedState.dwayneDiscussedBoylesButton) &&
!state.evidenceFollowupShown) {
state.evidenceFollowupShown = true;
- lineError = playBoyleLine(0x210, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x210, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.discussedNoteCheckbookEvidence != 0) {
- lineError = playBoyleLine(0x21a, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x21a, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (sharedState.dwayneDiscussedBoylesButton) {
- lineError = playBoyleLine(0x215, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x215, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (!runtime.startupScript().getFlagValue(kHaveLodgeAppFlag)) {
- lineError = playBoyleLine(0x21f, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x21f, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -433,34 +409,34 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playBoyleLine(0x22a, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x22a, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playBoyleLine(0x22e, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x22e, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else {
- lineError = playBoyleLine(0x233, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x233, "BOYLE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- clearBoyleTopicBuffer();
+ topics.clear();
}
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephMidgameShown) {
state.stephMidgameShown = true;
- lineError = playBoyleLine(0x267);
+ lineError = runtime.playDialogueLineWithVariant(0x267, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("DAY_5") && !state.dayFiveShown) {
state.dayFiveShown = true;
- lineError = playBoyleLine(0x26e, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x26e, "BOYLE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -468,8 +444,7 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("BURNED_TV_STATION") &&
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
- lineError = playSequence(kBoyleFollowupBurnedTvLines,
- ARRAYSIZE(kBoyleFollowupBurnedTvLines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleFollowupBurnedTvLines, ARRAYSIZE(kBoyleFollowupBurnedTvLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -483,39 +458,37 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0xd) ||
runtime.matchesResponseLine(selectedTopic, 0x20)) {
- return playBoyleLine(0x100, 1);
+ return runtime.playDialogueLineWithVariant(0x100, "BOYLE", 1);
}
if (runtime.matchesResponseLine(selectedTopic, 0xe)) {
- lineError = playSequence(kBoyleKeywordTopic0eLines,
- ARRAYSIZE(kBoyleKeywordTopic0eLines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleKeywordTopic0eLines, ARRAYSIZE(kBoyleKeywordTopic0eLines));
} else if (runtime.matchesAnyResponseLine(selectedTopic, kBoyleKeywordTopic0fTo12Lines,
ARRAYSIZE(kBoyleKeywordTopic0fTo12Lines))) {
- lineError = playBoyleLine(0xab);
+ lineError = runtime.playDialogueLineWithVariant(0xab, "BOYLE", 0);
} else if (runtime.matchesAnyResponseLine(selectedTopic, kBoyleKeywordTopic13To14Lines,
ARRAYSIZE(kBoyleKeywordTopic13To14Lines))) {
- lineError = playBoyleLine(0xb6, 3);
+ lineError = runtime.playDialogueLineWithVariant(0xb6, "BOYLE", 3);
} else if (runtime.matchesAnyResponseLine(selectedTopic, kBoyleKeywordTopic15To16Lines,
ARRAYSIZE(kBoyleKeywordTopic15To16Lines))) {
lineError = runtime.startupScript().getCurrentStoryDayIndex() >= 3
- ? playBoyleLine(0xc6)
- : playBoyleLine(0x243);
+ ? runtime.playDialogueLineWithVariant(0xc6, "BOYLE", 0)
+ : runtime.playDialogueLineWithVariant(0x243, "BOYLE", 0);
} else if (runtime.matchesResponseLine(selectedTopic, 0x17)) {
- lineError = playSequence(kBoyleKeywordTopic17Lines,
- ARRAYSIZE(kBoyleKeywordTopic17Lines));
+ lineError = runtime.playDialogueEntrySequence(kBoyleKeywordTopic17Lines, ARRAYSIZE(kBoyleKeywordTopic17Lines));
} else if (runtime.matchesAnyResponseLine(selectedTopic, kBoyleKeywordTopic18To1bLines,
ARRAYSIZE(kBoyleKeywordTopic18To1bLines))) {
if (!sharedState.dialogueStateD2eb0) {
lineError = runtime.playDialogueFst(kDialogueC019BFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBoyleLine(0x10e);
+ lineError = runtime.playDialogueLineWithVariant(0x10e, "BOYLE", 0);
} else {
- lineError = playBoyleLine(0x115, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x115, "BOYLE", 1);
}
} else if (runtime.matchesResponseLine(selectedTopic, 0x1d) ||
selectedTopic.equalsIgnoreCase(kBoyleArsonistTopic)) {
- lineError = playBoyleLine(0x11c);
+ lineError = runtime.playDialogueLineWithVariant(0x11c, "BOYLE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -525,18 +498,18 @@ Common::Error BoyleDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(kBoyleKeywordArsonResponse1Lines,
+ lineError = runtime.playDialogueEntrySequence(kBoyleKeywordArsonResponse1Lines,
ARRAYSIZE(kBoyleKeywordArsonResponse1Lines));
} else if (responseIndex == 2) {
- lineError = playBoyleLine(0x135);
+ lineError = runtime.playDialogueLineWithVariant(0x135, "BOYLE", 0);
} else {
lineError = Common::kNoError;
}
} else if (runtime.matchesResponseLine(selectedTopic, 0x1f)) {
- lineError = playSequence(kBoyleHaveLodgeAppEvidenceLines,
+ lineError = runtime.playDialogueEntrySequence(kBoyleHaveLodgeAppEvidenceLines,
ARRAYSIZE(kBoyleHaveLodgeAppEvidenceLines));
} else {
- lineError = playBoyleLine(0x243);
+ lineError = runtime.playDialogueLineWithVariant(0x243, "BOYLE", 0);
}
if (lineError.getCode() != Common::kNoError)
diff --git a/engines/harvester/npc/boyle_dialogue.h b/engines/harvester/npc/boyle_dialogue.h
index e9453e8217e..b205ab65c90 100644
--- a/engines/harvester/npc/boyle_dialogue.h
+++ b/engines/harvester/npc/boyle_dialogue.h
@@ -37,7 +37,6 @@ public:
bool burnedTvStationShown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = BoyleRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/buster_dialogue.cpp b/engines/harvester/npc/buster_dialogue.cpp
index d3f2e85fe71..598d4f425f1 100644
--- a/engines/harvester/npc/buster_dialogue.cpp
+++ b/engines/harvester/npc/buster_dialogue.cpp
@@ -32,8 +32,6 @@ namespace Harvester {
namespace {
-static const char *const kBusterNpc = "BUSTER";
-static const char *const kPcSpeaker = "PC";
static const char *const kDialogueC058FstPath = "GRAPHIC/FST/C058.FST";
static const char *const kDialogueC085FstPath = "GRAPHIC/FST/C085.FST";
static const char *const kDialogueC086FstPath = "GRAPHIC/FST/C086.FST";
@@ -71,130 +69,117 @@ static const int kBusterTopic0x48Line = 0x48;
static const int kBusterTopic0x49Line = 0x49;
static const DialogueLineEntry kBusterCorpsePhotoLines[] = {
- { 0x1884, kBusterNpc, 0 },
- { 0x1889, kPcSpeaker, 4 },
- { 0x188e, kBusterNpc, 2 },
- { 0x1895, kBusterNpc, 2 }
+ { 0x1884, "BUSTER", 0 },
+ { 0x1889, "PC", 4 },
+ { 0x188e, "BUSTER", 2 },
+ { 0x1895, "BUSTER", 2 }
};
static const DialogueLineEntry kBusterIntroLines[] = {
- { 0x163c, kBusterNpc, 2 },
- { 0x1640, kPcSpeaker, 0 },
- { 0x1644, kBusterNpc, 0 },
- { 0x1649, kPcSpeaker, 0 },
- { 0x164d, kBusterNpc, 0 },
- { 0x1654, kPcSpeaker, 0 },
- { 0x1658, kBusterNpc, 0 },
- { 0x165e, kPcSpeaker, 4 },
- { 0x1662, kBusterNpc, 0 },
- { 0x1669, kPcSpeaker, 0 },
- { 0x166e, kBusterNpc, 0 },
- { 0x1673, kPcSpeaker, 0 },
- { 0x1677, kBusterNpc, 0 },
- { 0x167e, kBusterNpc, 0 },
- { 0x1682, kBusterNpc, 2 },
- { 0x168e, kBusterNpc, 0 }
+ { 0x163c, "BUSTER", 2 },
+ { 0x1640, "PC", 0 },
+ { 0x1644, "BUSTER", 0 },
+ { 0x1649, "PC", 0 },
+ { 0x164d, "BUSTER", 0 },
+ { 0x1654, "PC", 0 },
+ { 0x1658, "BUSTER", 0 },
+ { 0x165e, "PC", 4 },
+ { 0x1662, "BUSTER", 0 },
+ { 0x1669, "PC", 0 },
+ { 0x166e, "BUSTER", 0 },
+ { 0x1673, "PC", 0 },
+ { 0x1677, "BUSTER", 0 },
+ { 0x167e, "BUSTER", 0 },
+ { 0x1682, "BUSTER", 2 },
+ { 0x168e, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterSecondIntroPreludeLines[] = {
- { 0x1828, kBusterNpc, 2 },
- { 0x182c, kPcSpeaker, 2 },
- { 0x1830, kBusterNpc, 2 }
+ { 0x1828, "BUSTER", 2 },
+ { 0x182c, "PC", 2 },
+ { 0x1830, "BUSTER", 2 }
};
static const DialogueLineEntry kBusterThirdIntroLines[] = {
- { 0x18c5, kBusterNpc, 2 },
- { 0x18c9, kPcSpeaker, 4 },
- { 0x18cd, kBusterNpc, 2 }
+ { 0x18c5, "BUSTER", 2 },
+ { 0x18c9, "PC", 4 },
+ { 0x18cd, "BUSTER", 2 }
};
static const DialogueLineEntry kBusterTopic0x28Or0x29LinesSequence[] = {
- { 0x1698, kBusterNpc, 0 },
- { 0x169c, kPcSpeaker, 4 },
- { 0x16a1, kBusterNpc, 0 }
+ { 0x1698, "BUSTER", 0 },
+ { 0x169c, "PC", 4 },
+ { 0x16a1, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x28Or0x29TailLines[] = {
- { 0x16ad, kBusterNpc, 2 },
- { 0x16b6, kBusterNpc, 0 }
+ { 0x16ad, "BUSTER", 2 },
+ { 0x16b6, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x32Lines[] = {
- { 0x170a, kPcSpeaker, 0 },
- { 0x170f, kBusterNpc, 0 },
- { 0x1710, kBusterNpc, 0 },
- { 0x1711, kBusterNpc, 0 },
- { 0x1712, kBusterNpc, 0 }
+ { 0x170a, "PC", 0 },
+ { 0x170f, "BUSTER", 0 },
+ { 0x1710, "BUSTER", 0 },
+ { 0x1711, "BUSTER", 0 },
+ { 0x1712, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x34Lines[] = {
- { 0x1727, kBusterNpc, 0 },
- { 0x1728, kBusterNpc, 0 },
- { 0x1729, kBusterNpc, 0 },
- { 0x172a, kBusterNpc, 0 },
- { 0x172b, kBusterNpc, 0 }
+ { 0x1727, "BUSTER", 0 },
+ { 0x1728, "BUSTER", 0 },
+ { 0x1729, "BUSTER", 0 },
+ { 0x172a, "BUSTER", 0 },
+ { 0x172b, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x36Lines[] = {
- { 0x173d, kPcSpeaker, 0 },
- { 0x1742, kBusterNpc, 0 },
- { 0x1749, kPcSpeaker, 0 },
- { 0x174d, kBusterNpc, 0 },
- { 0x174e, kBusterNpc, 0 },
- { 0x174f, kBusterNpc, 0 },
- { 0x1750, kBusterNpc, 2 },
- { 0x1762, kBusterNpc, 2 }
+ { 0x173d, "PC", 0 },
+ { 0x1742, "BUSTER", 0 },
+ { 0x1749, "PC", 0 },
+ { 0x174d, "BUSTER", 0 },
+ { 0x174e, "BUSTER", 0 },
+ { 0x174f, "BUSTER", 0 },
+ { 0x1750, "BUSTER", 2 },
+ { 0x1762, "BUSTER", 2 }
};
static const DialogueLineEntry kBusterTopic0x38ResponseTwoLines[] = {
- { 0x1787, kBusterNpc, 0 },
- { 0x1791, kBusterNpc, 0 },
- { 0x1796, kPcSpeaker, 0 },
- { 0x179d, kBusterNpc, 0 }
+ { 0x1787, "BUSTER", 0 },
+ { 0x1791, "BUSTER", 0 },
+ { 0x1796, "PC", 0 },
+ { 0x179d, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x3bTailLines[] = {
- { 0x17bb, kBusterNpc, 0 },
- { 0x17c3, kBusterNpc, 0 }
+ { 0x17bb, "BUSTER", 0 },
+ { 0x17c3, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x3eLines[] = {
- { 0x17cc, kBusterNpc, 0 },
- { 0x17cd, kBusterNpc, 0 },
- { 0x17ce, kBusterNpc, 0 },
- { 0x17db, kBusterNpc, 0 }
+ { 0x17cc, "BUSTER", 0 },
+ { 0x17cd, "BUSTER", 0 },
+ { 0x17ce, "BUSTER", 0 },
+ { 0x17db, "BUSTER", 0 }
};
static const DialogueLineEntry kBusterTopic0x40Or0x41PreludeLines[] = {
- { 0x17e4, kBusterNpc, 0 },
- { 0x17e5, kBusterNpc, 0 },
- { 0x17e6, kBusterNpc, 0 },
- { 0x17e7, kBusterNpc, 0 },
- { 0x17f7, kBusterNpc, 0 }
+ { 0x17e4, "BUSTER", 0 },
+ { 0x17e5, "BUSTER", 0 },
+ { 0x17e6, "BUSTER", 0 },
+ { 0x17e7, "BUSTER", 0 },
+ { 0x17f7, "BUSTER", 0 }
};
} // End of namespace
-bool BusterDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kBusterNpc);
-}
-
Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
Common::String topicBuffer;
int topicBufferLineIndex = -1;
- auto assignBusterTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(topicBuffer, topicBufferLineIndex,
- responseLineIndex, "Buster topic buffer");
- };
- auto playBusterLine = [&](int wavId, int headVariant = 0,
- const char *speakerId = kBusterNpc) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, speakerId, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+ DialogueTopicBuffer topics(runtime, topicBuffer, topicBufferLineIndex, "Buster topic buffer");
+
auto clearScreenToBlack = [&]() {
Graphics::Screen *screen = runtime.engine().getScreen();
if (!screen)
@@ -204,7 +189,7 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
screen->update();
};
auto playFatalBusterBranch = [&](int wavId, int headVariant = 0) -> Common::Error {
- Common::Error lineError = playBusterLine(wavId, headVariant);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(wavId, "BUSTER", headVariant);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -230,17 +215,17 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
- return playBusterLine(0x187b);
+ return runtime.playDialogueLineWithVariant(0x187b, "BUSTER", 0);
}
if (isCorpsePhoto(usedItemName)) {
sharedState.discussedCasketPhotoEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
- return playSequence(kBusterCorpsePhotoLines, ARRAYSIZE(kBusterCorpsePhotoLines));
+ return runtime.playDialogueEntrySequence(kBusterCorpsePhotoLines, ARRAYSIZE(kBusterCorpsePhotoLines));
}
if (isBlackmailEvidence(usedItemName)) {
sharedState.discussedNoteCheckbookEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
- Common::Error lineError = playBusterLine(0x189b);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x189b, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -251,38 +236,38 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playBusterLine(0x18a6, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x18a6, "BUSTER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBusterLine(0x18aa, 0, kPcSpeaker);
+ lineError = runtime.playDialogueLineWithVariant(0x18aa, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playBusterLine(0x18ae);
+ return runtime.playDialogueLineWithVariant(0x18ae, "BUSTER", 0);
}
if (responseIndex == 2) {
- lineError = playBusterLine(0x18b5, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x18b5, "BUSTER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playBusterLine(0x18be, 2);
+ return runtime.playDialogueLineWithVariant(0x18be, "BUSTER", 2);
}
return Common::kNoError;
}
- return playBusterLine(0x1875);
+ return runtime.playDialogueLineWithVariant(0x1875, "BUSTER", 0);
}
if (_state.introPending) {
_state.introPending = false;
_state.secondIntroPending = true;
- Common::Error lineError = playSequence(kBusterIntroLines, ARRAYSIZE(kBusterIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterIntroLines, ARRAYSIZE(kBusterIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterIntroTopicBufferLine);
+ topics.assign(kBusterIntroTopicBufferLine);
} else if (_state.secondIntroPending) {
_state.secondIntroPending = false;
_state.thirdIntroPending = true;
- Common::Error lineError = playSequence(
- kBusterSecondIntroPreludeLines, ARRAYSIZE(kBusterSecondIntroPreludeLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterSecondIntroPreludeLines,
+ ARRAYSIZE(kBusterSecondIntroPreludeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -295,12 +280,12 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 1)
return playFatalBusterBranch(0x183a, 2);
if (responseIndex == 2) {
- lineError = playBusterLine(0x1841);
+ lineError = runtime.playDialogueLineWithVariant(0x1841, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!_state.secondIntroResponseTwoSeen) {
- lineError = playBusterLine(0x185e);
+ lineError = runtime.playDialogueLineWithVariant(0x185e, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -308,7 +293,7 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
_state.secondIntroPending = true;
_state.thirdIntroPending = false;
} else {
- lineError = playBusterLine(0x1845);
+ lineError = runtime.playDialogueLineWithVariant(0x1845, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -321,7 +306,7 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (followupResponseIndex == 1)
return playFatalBusterBranch(0x1850);
if (followupResponseIndex == 2) {
- lineError = playBusterLine(0x1858);
+ lineError = runtime.playDialogueLineWithVariant(0x1858, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -329,9 +314,9 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
} else if (_state.thirdIntroPending) {
_state.thirdIntroPending = false;
- return playSequence(kBusterThirdIntroLines, ARRAYSIZE(kBusterThirdIntroLines));
+ return runtime.playDialogueEntrySequence(kBusterThirdIntroLines, ARRAYSIZE(kBusterThirdIntroLines));
} else {
- return playBusterLine(0x1868);
+ return runtime.playDialogueLineWithVariant(0x1868, "BUSTER", 0);
}
for (;;) {
@@ -343,32 +328,32 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
if (runtime.matchesResponseLine(selectedTopic, kBusterExitTopicLine))
- return playBusterLine(0x1818);
+ return runtime.playDialogueLineWithVariant(0x1818, "BUSTER", 0);
if (runtime.matchesAnyResponseLine(selectedTopic, kBusterTopic0x28Or0x29Lines,
ARRAYSIZE(kBusterTopic0x28Or0x29Lines))) {
- Common::Error lineError = playSequence(
- kBusterTopic0x28Or0x29LinesSequence, ARRAYSIZE(kBusterTopic0x28Or0x29LinesSequence));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterTopic0x28Or0x29LinesSequence,
+ ARRAYSIZE(kBusterTopic0x28Or0x29LinesSequence));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC085FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(
- kBusterTopic0x28Or0x29TailLines, ARRAYSIZE(kBusterTopic0x28Or0x29TailLines));
+ lineError = runtime.playDialogueEntrySequence(kBusterTopic0x28Or0x29TailLines,
+ ARRAYSIZE(kBusterTopic0x28Or0x29TailLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(0x2b);
+ topics.assign(0x2b);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kBusterTopic0x2cOr0x2dLines,
ARRAYSIZE(kBusterTopic0x2cOr0x2dLines))) {
- Common::Error lineError = playBusterLine(0x16be);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x16be, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playBusterLine(0x16c5);
+ lineError = runtime.playDialogueLineWithVariant(0x16c5, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -381,7 +366,7 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 1)
return playFatalBusterBranch(0x16d0);
if (responseIndex == 2) {
- lineError = playBusterLine(0x16d6);
+ lineError = runtime.playDialogueLineWithVariant(0x16d6, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -392,7 +377,7 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (followupResponseIndex == 1) {
- lineError = playBusterLine(0x16e2);
+ lineError = runtime.playDialogueLineWithVariant(0x16e2, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -405,11 +390,11 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (nestedResponseIndex == 1)
return playFatalBusterBranch(0x16ef);
if (nestedResponseIndex == 2) {
- lineError = playBusterLine(0x16f6);
+ lineError = runtime.playDialogueLineWithVariant(0x16f6, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(0x31);
+ topics.assign(0x31);
}
} else if (followupResponseIndex == 2) {
return playFatalBusterBranch(0x1702);
@@ -419,37 +404,34 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x32Line)) {
- Common::Error lineError = playSequence(
- kBusterTopic0x32Lines, ARRAYSIZE(kBusterTopic0x32Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterTopic0x32Lines, ARRAYSIZE(kBusterTopic0x32Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x32TopicBufferLine);
+ topics.assign(kBusterTopic0x32TopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x34Line)) {
- Common::Error lineError = playSequence(
- kBusterTopic0x34Lines, ARRAYSIZE(kBusterTopic0x34Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterTopic0x34Lines, ARRAYSIZE(kBusterTopic0x34Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x34TopicBufferLine);
+ topics.assign(kBusterTopic0x34TopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x36Line)) {
- Common::Error lineError = playSequence(
- kBusterTopic0x36Lines, ARRAYSIZE(kBusterTopic0x36Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterTopic0x36Lines, ARRAYSIZE(kBusterTopic0x36Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x36TopicBufferLine);
+ topics.assign(kBusterTopic0x36TopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x38Line)) {
- Common::Error lineError = playBusterLine(0x176b);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x176b, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC058FstPath);
@@ -463,20 +445,20 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1)
- return playBusterLine(0x1781);
+ return runtime.playDialogueLineWithVariant(0x1781, "BUSTER", 0);
if (responseIndex == 2) {
- lineError = playSequence(
- kBusterTopic0x38ResponseTwoLines, ARRAYSIZE(kBusterTopic0x38ResponseTwoLines));
+ lineError = runtime.playDialogueEntrySequence(kBusterTopic0x38ResponseTwoLines,
+ ARRAYSIZE(kBusterTopic0x38ResponseTwoLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- assignBusterTopicBuffer(kBusterTopic0x38TopicBufferLine);
+ topics.assign(kBusterTopic0x38TopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x3bLine)) {
- Common::Error lineError = playBusterLine(0x17a5);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x17a5, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -487,36 +469,35 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playBusterLine(0x17b3);
+ lineError = runtime.playDialogueLineWithVariant(0x17b3, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playBusterLine(0x17b7);
+ lineError = runtime.playDialogueLineWithVariant(0x17b7, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playSequence(kBusterTopic0x3bTailLines, ARRAYSIZE(kBusterTopic0x3bTailLines));
+ lineError = runtime.playDialogueEntrySequence(kBusterTopic0x3bTailLines, ARRAYSIZE(kBusterTopic0x3bTailLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x3bTopicBufferLine);
+ topics.assign(kBusterTopic0x3bTopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x3eLine)) {
- Common::Error lineError = playSequence(
- kBusterTopic0x3eLines, ARRAYSIZE(kBusterTopic0x3eLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterTopic0x3eLines, ARRAYSIZE(kBusterTopic0x3eLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x3eTopicBufferLine);
+ topics.assign(kBusterTopic0x3eTopicBufferLine);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kBusterTopic0x40Or0x41Lines,
ARRAYSIZE(kBusterTopic0x40Or0x41Lines))) {
- Common::Error lineError = playSequence(kBusterTopic0x40Or0x41PreludeLines,
+ Common::Error lineError = runtime.playDialogueEntrySequence(kBusterTopic0x40Or0x41PreludeLines,
ARRAYSIZE(kBusterTopic0x40Or0x41PreludeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -530,22 +511,22 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 1)
return playFatalBusterBranch(0x1804);
if (responseIndex == 2) {
- lineError = playBusterLine(0x180b);
+ lineError = runtime.playDialogueLineWithVariant(0x180b, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x40TopicBufferLine);
+ topics.assign(kBusterTopic0x40TopicBufferLine);
}
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kBusterTopic0x44Or0x45Or0x46Lines,
ARRAYSIZE(kBusterTopic0x44Or0x45Or0x46Lines))) {
- Common::Error lineError = playBusterLine(0x181e, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x181e, "BUSTER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignBusterTopicBuffer(kBusterTopic0x44TopicBufferLine);
+ topics.assign(kBusterTopic0x44TopicBufferLine);
continue;
}
@@ -553,7 +534,7 @@ Common::Error BusterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return playFatalBusterBranch(0x18df, 2);
if (runtime.matchesResponseLine(selectedTopic, kBusterTopic0x49Line)) {
- Common::Error lineError = playBusterLine(0x186f);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x186f, "BUSTER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/buster_dialogue.h b/engines/harvester/npc/buster_dialogue.h
index dde1dd192ba..6604bd2b578 100644
--- a/engines/harvester/npc/buster_dialogue.h
+++ b/engines/harvester/npc/buster_dialogue.h
@@ -35,7 +35,6 @@ public:
bool secondIntroResponseTwoSeen = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = BusterRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/butcher_dialogue.cpp b/engines/harvester/npc/butcher_dialogue.cpp
index 39521964311..9cfd4f3bada 100644
--- a/engines/harvester/npc/butcher_dialogue.cpp
+++ b/engines/harvester/npc/butcher_dialogue.cpp
@@ -29,8 +29,6 @@ namespace Harvester {
namespace {
-static const char *const kButcherNpc = "BUTCHER";
-static const char *const kPcSpeaker = "PC";
static const char *const kDialogueC060FstPath = "GRAPHIC/FST/C060.FST";
static const char *const kDialogueC060AFstPath = "GRAPHIC/FST/C060A.FST";
static const char *const kDialogueC119FstPath = "GRAPHIC/FST/C119.FST";
@@ -42,48 +40,44 @@ static const char *const kDialogueC123AFstPath = "GRAPHIC/FST/C123A.FST";
static const char *const kDialogueC123BFstPath = "GRAPHIC/FST/C123B.FST";
static const DialogueLineEntry kButcherWhaleyPhotoLines[] = {
- { 0x1a5a, kButcherNpc, 0 },
- { 0x1a5e, kPcSpeaker, 0 },
- { 0x1a62, kButcherNpc, 1 }
+ { 0x1a5a, "BUTCHER", 0 },
+ { 0x1a5e, "PC", 0 },
+ { 0x1a62, "BUTCHER", 1 }
};
static const DialogueLineEntry kButcherCasketPhotoLines[] = {
- { 0x1a69, kButcherNpc, 0 },
- { 0x1a6d, kPcSpeaker, 4 },
- { 0x1a71, kButcherNpc, 1 },
- { 0x1a76, kPcSpeaker, 0 },
- { 0x1a7a, kButcherNpc, 0 }
+ { 0x1a69, "BUTCHER", 0 },
+ { 0x1a6d, "PC", 4 },
+ { 0x1a71, "BUTCHER", 1 },
+ { 0x1a76, "PC", 0 },
+ { 0x1a7a, "BUTCHER", 0 }
};
static const DialogueLineEntry kButcherLedgerLines[] = {
- { 0x1a80, kButcherNpc, 0 },
- { 0x1a85, kPcSpeaker, 0 },
- { 0x1a8a, kButcherNpc, 0 },
- { 0x1a92, kButcherNpc, 0 },
- { 0x1a96, kButcherNpc, 2 }
+ { 0x1a80, "BUTCHER", 0 },
+ { 0x1a85, "PC", 0 },
+ { 0x1a8a, "BUTCHER", 0 },
+ { 0x1a92, "BUTCHER", 0 },
+ { 0x1a96, "BUTCHER", 2 }
};
static const DialogueLineEntry kButcherOpeningQuestionLines[] = {
- { 0x192a, kPcSpeaker, 0 },
- { 0x192f, kButcherNpc, 0 },
- { 0x1933, kPcSpeaker, 0 },
- { 0x1938, kButcherNpc, 2 }
+ { 0x192a, "PC", 0 },
+ { 0x192f, "BUTCHER", 0 },
+ { 0x1933, "PC", 0 },
+ { 0x1938, "BUTCHER", 2 }
};
static const DialogueLineEntry kButcherLodgeTopicLines[] = {
- { 0x1a07, kButcherNpc, 0 },
- { 0x1a0d, kPcSpeaker, 0 },
- { 0x1a11, kButcherNpc, 1 },
- { 0x1a18, kPcSpeaker, 0 },
- { 0x1a1c, kButcherNpc, 1 }
+ { 0x1a07, "BUTCHER", 0 },
+ { 0x1a0d, "PC", 0 },
+ { 0x1a11, "BUTCHER", 1 },
+ { 0x1a18, "PC", 0 },
+ { 0x1a1c, "BUTCHER", 1 }
};
} // End of namespace
-bool ButcherDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kButcherNpc);
-}
-
Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
ButcherRoomDialogueState &state = _state;
@@ -92,23 +86,8 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.currentTopicBuffer.clear();
state.currentTopicBufferLineIndex = -1;
- auto assignButcherTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(butcherTopicBuffer, butcherTopicBufferLineIndex,
- responseLineIndex, "Butcher topic buffer");
- };
- auto clearButcherTopicBuffer = [&]() {
- butcherTopicBuffer.clear();
- butcherTopicBufferLineIndex = -1;
- };
- auto playButcherLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kButcherNpc, headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kPcSpeaker, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+ DialogueTopicBuffer topics(runtime, butcherTopicBuffer, butcherTopicBufferLineIndex, "Butcher topic buffer");
+
auto hasMeatPermission = [&]() {
return runtime.startupScript().isObjectInInventory("MEAT_PERMISSION0") ||
runtime.startupScript().isObjectInInventory("MEAT_PERMISSION");
@@ -119,14 +98,14 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedWhaleyHerrillPhoto = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
- return playSequence(kButcherWhaleyPhotoLines, ARRAYSIZE(kButcherWhaleyPhotoLines));
+ return runtime.playDialogueEntrySequence(kButcherWhaleyPhotoLines, ARRAYSIZE(kButcherWhaleyPhotoLines));
}
if (usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
sharedState.discussedCasketPhotoEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownPhotoOfCorpse, true);
- return playSequence(kButcherCasketPhotoLines, ARRAYSIZE(kButcherCasketPhotoLines));
+ return runtime.playDialogueEntrySequence(kButcherCasketPhotoLines, ARRAYSIZE(kButcherCasketPhotoLines));
}
if ((usedItemName.equalsIgnoreCase("LEDGER") ||
usedItemName.equalsIgnoreCase("LEDGER2")) &&
@@ -134,7 +113,7 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedLedgerEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownLedgersToAnyone, true);
- return playSequence(kButcherLedgerLines, ARRAYSIZE(kButcherLedgerLines));
+ return runtime.playDialogueEntrySequence(kButcherLedgerLines, ARRAYSIZE(kButcherLedgerLines));
}
if (usedItemName.equalsIgnoreCase("NOTE") ||
usedItemName.equalsIgnoreCase("NOTE_PHOTOCOPY") ||
@@ -143,10 +122,10 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedNoteCheckbookEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownEvidenceOfBlackmail, true);
- return playButcherLine(0x1a9e);
+ return runtime.playDialogueLineWithVariant(0x1a9e, "BUTCHER", 0);
}
if (usedItemName.equalsIgnoreCase("MEAT_PERMISSION")) {
- Common::Error lineError = playButcherLine(0x1ac4, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1ac4, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -155,7 +134,7 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
- lineError = playButcherLine(0x1ace, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1ace, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC060AFstPath);
@@ -168,50 +147,50 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
}
- return playButcherLine(0x1a54);
+ return runtime.playDialogueLineWithVariant(0x1a54, "BUTCHER", 0);
}
if (state.introPending) {
state.introPending = false;
- Common::Error lineError = playButcherLine(0x1902);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1902, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x1906);
+ lineError = runtime.playDialogueLineWithVariant(0x1906, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x190a);
+ lineError = runtime.playDialogueLineWithVariant(0x190a, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(sharedState.dialogueStateD2ed0 ? 0x1913 : 0x190f);
+ lineError = runtime.playDialogueLineWithVariant(sharedState.dialogueStateD2ed0 ? 0x1913 : 0x190f, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x1917, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1917, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x191d);
+ lineError = runtime.playDialogueLineWithVariant(0x191d, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x1921, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1921, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(0x260);
+ topics.assign(0x260);
} else {
- Common::Error lineError = playButcherLine(0x1a47);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1a47, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!hasMeatPermission() && runtime.startupScript().getCurrentStoryDayIndex() <= 3)
- assignButcherTopicBuffer(0x261);
+ topics.assign(0x261);
else
- clearButcherTopicBuffer();
+ topics.clear();
}
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephMidgameShown) {
state.stephMidgameShown = true;
- Common::Error lineError = playButcherLine(0x1aa7, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1aa7, "BUTCHER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC123BFstPath);
@@ -220,7 +199,7 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.startupScript().getFlagValue("DAY_5") && !state.dayFiveShown) {
state.dayFiveShown = true;
- Common::Error lineError = playButcherLine(0x1ab6, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1ab6, "BUTCHER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC119CFstPath);
@@ -239,12 +218,12 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (selectedTopic.equalsIgnoreCase(runtime.genericByeTopic()) ||
runtime.matchesResponseLine(selectedTopic, 0x262)) {
- return playButcherLine(0x1a41);
+ return runtime.playDialogueLineWithVariant(0x1a41, "BUTCHER", 0);
}
if (runtime.matchesResponseLine(selectedTopic, 0x263)) {
- Common::Error lineError = playSequence(
- kButcherOpeningQuestionLines, ARRAYSIZE(kButcherOpeningQuestionLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kButcherOpeningQuestionLines,
+ ARRAYSIZE(kButcherOpeningQuestionLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -254,45 +233,45 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playButcherLine(0x1943, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x1943, "BUTCHER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC119FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playButcherLine(0x1950, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1950, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x1955);
+ lineError = runtime.playDialogueLineWithVariant(0x1955, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x195a);
+ lineError = runtime.playDialogueLineWithVariant(0x195a, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(hasMeatPermission() ? 0x266 : 0x265);
+ topics.assign(hasMeatPermission() ? 0x266 : 0x265);
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x267) && !hasMeatPermission()) {
- Common::Error lineError = playPcLine(0x1964);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1964, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x1969);
+ lineError = runtime.playDialogueLineWithVariant(0x1969, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC060FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x1975);
+ lineError = runtime.playDialogueLineWithVariant(0x1975, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC119AFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x1980);
+ lineError = runtime.playDialogueLineWithVariant(0x1980, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -302,134 +281,134 @@ Common::Error ButcherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playButcherLine(0x198b);
+ lineError = runtime.playDialogueLineWithVariant(0x198b, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dadMeatPermissionState = 1;
(void)runtime.startupScript().addRuntimeObjectToInventory("MEAT_PERMISSION0");
- assignButcherTopicBuffer(0x269);
+ topics.assign(0x269);
} else if (responseIndex == 2) {
- lineError = playButcherLine(0x1992, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1992, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(0x26a);
+ topics.assign(0x26a);
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x26b)) {
- Common::Error lineError = playButcherLine(0x199c);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x199c, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC119BFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19a7);
+ lineError = runtime.playDialogueLineWithVariant(0x19a7, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19ae);
+ lineError = runtime.playDialogueLineWithVariant(0x19ae, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19b3, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x19b3, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC123FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19bf, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x19bf, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(hasMeatPermission() ? 0x26d : 0x26c);
+ topics.assign(hasMeatPermission() ? 0x26d : 0x26c);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x26e)) {
- Common::Error lineError = playButcherLine(0x19ca);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x19ca, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.momFatherTopicState == 0) {
- lineError = playPcLine(0x19ce);
+ lineError = runtime.playDialogueLineWithVariant(0x19ce, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else {
- lineError = playPcLine(0x19d2);
+ lineError = runtime.playDialogueLineWithVariant(0x19d2, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19d6);
+ lineError = runtime.playDialogueLineWithVariant(0x19d6, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (sharedState.dialogueStateD2ed0) {
- lineError = playPcLine(0x19dc);
+ lineError = runtime.playDialogueLineWithVariant(0x19dc, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19e1);
+ lineError = runtime.playDialogueLineWithVariant(0x19e1, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x19e5, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x19e5, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x19e9, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x19e9, "BUTCHER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(0x26f);
+ topics.assign(0x26f);
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x270)) {
- Common::Error lineError = playButcherLine(0x19f6);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x19f6, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC123AFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(hasMeatPermission() ? 0x272 : 0x271);
+ topics.assign(hasMeatPermission() ? 0x272 : 0x271);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x273) ||
runtime.matchesResponseLine(selectedTopic, 0x274)) {
sharedState.discussedLodgeTopic = true;
- Common::Error lineError = playSequence(
- kButcherLodgeTopicLines, ARRAYSIZE(kButcherLodgeTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kButcherLodgeTopicLines,
+ ARRAYSIZE(kButcherLodgeTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(hasMeatPermission() ? 0x276 : 0x275);
+ topics.assign(hasMeatPermission() ? 0x276 : 0x275);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x277)) {
- Common::Error lineError = playPcLine(0x1a24, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1a24, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playButcherLine(0x1a29, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1a29, "BUTCHER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!sharedState.dialogueStateD2f04) {
sharedState.dialogueStateD2f04 = true;
- lineError = playPcLine(0x1a2d);
+ lineError = runtime.playDialogueLineWithVariant(0x1a2d, "PC", 0);
} else {
- lineError = playPcLine(0x1a31);
+ lineError = runtime.playDialogueLineWithVariant(0x1a31, "PC", 0);
if (lineError.getCode() == Common::kNoError)
- lineError = playButcherLine(0x1a36, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x1a36, "BUTCHER", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignButcherTopicBuffer(0x278);
+ topics.assign(0x278);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x279))
continue;
- Common::Error lineError = playButcherLine(0x1a4e);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1a4e, "BUTCHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/butcher_dialogue.h b/engines/harvester/npc/butcher_dialogue.h
index 9a63fd69e29..f6c1eec6b9c 100644
--- a/engines/harvester/npc/butcher_dialogue.h
+++ b/engines/harvester/npc/butcher_dialogue.h
@@ -36,7 +36,6 @@ public:
int currentTopicBufferLineIndex = -1;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = ButcherRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/chessmaster_dialogue.cpp b/engines/harvester/npc/chessmaster_dialogue.cpp
index ad4a21c3002..96a47521eb2 100644
--- a/engines/harvester/npc/chessmaster_dialogue.cpp
+++ b/engines/harvester/npc/chessmaster_dialogue.cpp
@@ -35,7 +35,6 @@ namespace Harvester {
namespace {
-static const char *const kChessmasterNpc = "CHESSMASTER";
static const char *const kChessSolvedFlag = "CHESS_SOLVED";
static const char *const kChessKingMonsterActionTag = "ADD_CHESS_KING_MONSTER";
static const int kChessmasterSlashDamageType = 2;
@@ -353,13 +352,9 @@ static Common::Error runChessmasterThreeMovePuzzle(DialogueRuntime &runtime, boo
} // End of namespace
-bool ChessmasterDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kChessmasterNpc);
-}
-
Common::Error ChessmasterDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
- Common::Error lineError = runtime.playDialogueLine(0x4115, kChessmasterNpc);
+ Common::Error lineError = runtime.playDialogueLine(0x4115, "CHESSMASTER");
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -370,7 +365,7 @@ Common::Error ChessmasterDialogueHandler::handleDialogue(DialogueRuntime &runtim
bool solvedPuzzle = false;
if (responseIndex == 1) {
- lineError = runtime.playDialogueLineWithVariant(0x4122, kChessmasterNpc, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x4122, "CHESSMASTER", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -382,7 +377,7 @@ Common::Error ChessmasterDialogueHandler::handleDialogue(DialogueRuntime &runtim
}
if (responseIndex != 1 || !solvedPuzzle) {
- lineError = runtime.playDialogueLineWithVariant(0x4126, kChessmasterNpc, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x4126, "CHESSMASTER", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -405,7 +400,7 @@ Common::Error ChessmasterDialogueHandler::handleDialogue(DialogueRuntime &runtim
InteractionResult interaction;
// C125.FST already shows the chessmaster death; do not queue the room death bank again.
if (runtime.startupScript().finalizeRuntimeNpcDeathOrMonsterfy(
- kChessmasterNpc, kChessmasterSlashDamageType)) {
+ "CHESSMASTER", kChessmasterSlashDamageType)) {
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
}
diff --git a/engines/harvester/npc/chessmaster_dialogue.h b/engines/harvester/npc/chessmaster_dialogue.h
index 867e94d7453..faa7ff24021 100644
--- a/engines/harvester/npc/chessmaster_dialogue.h
+++ b/engines/harvester/npc/chessmaster_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class ChessmasterDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/cloak_atnd_dialogue.cpp b/engines/harvester/npc/cloak_atnd_dialogue.cpp
index d8a6103cb67..ce89b927d66 100644
--- a/engines/harvester/npc/cloak_atnd_dialogue.cpp
+++ b/engines/harvester/npc/cloak_atnd_dialogue.cpp
@@ -28,7 +28,6 @@ namespace Harvester {
namespace {
-static const char *const kCloakAtndNpc = "CLOAK_ATND";
static const char *const kCleanedClothesFlag = "CLEANED_CLOTHES";
static const char *const kCleanClothesActionTag = "CLEAN_CLOTHES";
static const char *const kPaymentItemName = "BARCASHFIVE";
@@ -36,10 +35,6 @@ static const int kNeedCleaningPaymentLine = 0x1066;
} // End of namespace
-bool CloakAtndDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kCloakAtndNpc);
-}
-
Common::Error CloakAtndDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &) {
if (!usedItemName.empty()) {
@@ -58,7 +53,7 @@ Common::Error CloakAtndDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue(kCleanedClothesFlag))
return Common::kNoError;
- return runtime.playDialogueLine(kNeedCleaningPaymentLine, kCloakAtndNpc);
+ return runtime.playDialogueLine(kNeedCleaningPaymentLine, "CLOAK_ATND");
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/cloak_atnd_dialogue.h b/engines/harvester/npc/cloak_atnd_dialogue.h
index 44a749eef07..2a4bb404998 100644
--- a/engines/harvester/npc/cloak_atnd_dialogue.h
+++ b/engines/harvester/npc/cloak_atnd_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class CloakAtndDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/curator_dialogue.cpp b/engines/harvester/npc/curator_dialogue.cpp
index 571809353aa..127b80cb5c6 100644
--- a/engines/harvester/npc/curator_dialogue.cpp
+++ b/engines/harvester/npc/curator_dialogue.cpp
@@ -28,26 +28,20 @@ namespace Harvester {
namespace {
-static const char *const kCuratorNpc = "CURATOR";
-static const char *const kPcSpeaker = "PC";
static const int kCuratorResponseLine = 0x4a;
static const DialogueLineEntry kCuratorTailLines[] = {
- { 0x43a, kCuratorNpc, 0 },
- { 0x43b, kCuratorNpc, 0 },
- { 0x447, kPcSpeaker, 0 },
- { 0x44b, kCuratorNpc, 3 }
+ { 0x43a, "CURATOR", 0 },
+ { 0x43b, "CURATOR", 0 },
+ { 0x447, "PC", 0 },
+ { 0x44b, "CURATOR", 3 }
};
} // End of namespace
-bool CuratorDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kCuratorNpc);
-}
-
Common::Error CuratorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
- Common::Error lineError = runtime.playDialogueLineWithVariant(0x425, kCuratorNpc, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x425, "CURATOR", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -57,9 +51,9 @@ Common::Error CuratorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = runtime.playDialogueLineWithVariant(0x430, kCuratorNpc, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x430, "CURATOR", 3);
} else if (responseIndex == 2) {
- lineError = runtime.playDialogueLineWithVariant(0x435, kCuratorNpc, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x435, "CURATOR", 0);
} else {
lineError = Common::kNoError;
}
diff --git a/engines/harvester/npc/curator_dialogue.h b/engines/harvester/npc/curator_dialogue.h
index 89ad1b0f654..2a060f93a9d 100644
--- a/engines/harvester/npc/curator_dialogue.h
+++ b/engines/harvester/npc/curator_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class CuratorDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/dad_dialogue.cpp b/engines/harvester/npc/dad_dialogue.cpp
index aead72a156c..a16063882f1 100644
--- a/engines/harvester/npc/dad_dialogue.cpp
+++ b/engines/harvester/npc/dad_dialogue.cpp
@@ -30,8 +30,6 @@ namespace Harvester {
namespace {
-static const char *const kDadNpc = "DAD";
-static const char *const kPcSpeaker = "PC";
static const char *const kInventoryOwnerName = "INVENTORY";
static const char *const kEnglishDadIntroResponseMenu = "1. I'd like that./2. I'd rather not.";
static const int kFrenchDadIntroResponseMenuLineIndex = 0x328;
@@ -40,61 +38,61 @@ static const char *const kDialogueC112S4FstPath = "GRAPHIC/FST/C112S4.FST";
static const char *const kDialogueC112S7FstPath = "GRAPHIC/FST/C112S7.FST";
static const DialogueLineEntry kDadIntroLines[] = {
- { 0x39a5, kDadNpc, 0 },
- { 0x39a9, kPcSpeaker, 0 },
- { 0x39ad, kDadNpc, 0 },
- { 0x39b1, kPcSpeaker, 2 }
+ { 0x39a5, "DAD", 0 },
+ { 0x39a9, "PC", 0 },
+ { 0x39ad, "DAD", 0 },
+ { 0x39b1, "PC", 2 }
};
static const DialogueLineEntry kDadIntroContinuationLines[] = {
- { 0x39b5, kDadNpc, 0 },
- { 0x39ba, kPcSpeaker, 3 }
+ { 0x39b5, "DAD", 0 },
+ { 0x39ba, "PC", 3 }
};
static const DialogueLineEntry kDadOfferPromptLines[] = {
- { 0x39c2, kPcSpeaker, 2 },
- { 0x39c6, kDadNpc, 0 }
+ { 0x39c2, "PC", 2 },
+ { 0x39c6, "DAD", 0 }
};
static const DialogueLineEntry kDadOfferAcceptedLines[] = {
- { 0x39d3, kDadNpc, 0 },
- { 0x39d4, kDadNpc, 0 },
- { 0x39d5, kDadNpc, 0 },
- { 0x39d6, kDadNpc, 0 },
- { 0x39d7, kDadNpc, 0 }
+ { 0x39d3, "DAD", 0 },
+ { 0x39d4, "DAD", 0 },
+ { 0x39d5, "DAD", 0 },
+ { 0x39d6, "DAD", 0 },
+ { 0x39d7, "DAD", 0 }
};
static const DialogueLineEntry kDadOfferClosingLines[] = {
- { 0x39e6, kPcSpeaker, 0 },
- { 0x39eb, kDadNpc, 0 }
+ { 0x39e6, "PC", 0 },
+ { 0x39eb, "DAD", 0 }
};
static const DialogueLineEntry kDadMeatPermissionUnavailableLines[] = {
- { 0x39fe, kPcSpeaker, 0 },
- { 0x3a02, kDadNpc, 0 }
+ { 0x39fe, "PC", 0 },
+ { 0x3a02, "DAD", 0 }
};
static const DialogueLineEntry kDadWhaleyPhotoLines[] = {
- { 0x3a41, kDadNpc, 0 },
- { 0x3a46, kPcSpeaker, 0 },
- { 0x3a4a, kDadNpc, 0 }
+ { 0x3a41, "DAD", 0 },
+ { 0x3a46, "PC", 0 },
+ { 0x3a4a, "DAD", 0 }
};
static const DialogueLineEntry kDadBlackmailEvidenceLines[] = {
- { 0x3a51, kDadNpc, 0 },
- { 0x3a55, kPcSpeaker, 0 },
- { 0x3a59, kDadNpc, 0 }
+ { 0x3a51, "DAD", 0 },
+ { 0x3a55, "PC", 0 },
+ { 0x3a59, "DAD", 0 }
};
static const DialogueLineEntry kDadMeatPermissionConversionLines[] = {
- { 0x39f2, kPcSpeaker, 0 },
- { 0x39f7, kDadNpc, 0 }
+ { 0x39f2, "PC", 0 },
+ { 0x39f7, "DAD", 0 }
};
static const DialogueLineEntry kDadLodgeTopicLines[] = {
- { 0x3a7d, kDadNpc, 0 },
- { 0x3a83, kPcSpeaker, 0 },
- { 0x3a88, kDadNpc, 0 }
+ { 0x3a7d, "DAD", 0 },
+ { 0x3a83, "PC", 0 },
+ { 0x3a88, "DAD", 0 }
};
static Common::String getDadIntroResponseMenu(DialogueRuntime &runtime) {
@@ -117,22 +115,12 @@ static Common::String getDadIntroResponseMenu(DialogueRuntime &runtime) {
} // End of namespace
-bool DadDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kDadNpc);
-}
-
Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
DadRoomDialogueState &state = _state;
- auto playDadLine = [&](int wavId, const char *speakerId = kDadNpc,
- int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, speakerId, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+
auto playDadMeatPermissionConversion = [&]() -> Common::Error {
- Common::Error lineError = playSequence(kDadMeatPermissionConversionLines,
+ Common::Error lineError = runtime.playDialogueEntrySequence(kDadMeatPermissionConversionLines,
ARRAYSIZE(kDadMeatPermissionConversionLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -158,7 +146,7 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
};
if (runtime.startupScript().getFlagValue("TAKING_BONDAGE")) {
- Common::Error lineError = playDadLine(0x3a61);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3a61, "DAD", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -166,33 +154,33 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playDadLine(0x3a6b);
+ return runtime.playDialogueLineWithVariant(0x3a6b, "DAD", 0);
}
if (!usedItemName.empty()) {
if (usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
- return playDadLine(0x3a39);
+ return runtime.playDialogueLineWithVariant(0x3a39, "DAD", 0);
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
- return playSequence(kDadWhaleyPhotoLines, ARRAYSIZE(kDadWhaleyPhotoLines));
+ return runtime.playDialogueEntrySequence(kDadWhaleyPhotoLines, ARRAYSIZE(kDadWhaleyPhotoLines));
}
if (isBlackmailEvidence(usedItemName)) {
sharedState.discussedNoteCheckbookEvidence = 1;
- return playSequence(kDadBlackmailEvidenceLines, ARRAYSIZE(kDadBlackmailEvidenceLines));
+ return runtime.playDialogueEntrySequence(kDadBlackmailEvidenceLines, ARRAYSIZE(kDadBlackmailEvidenceLines));
}
if (usedItemName.equalsIgnoreCase("MEAT_PERMISSION0")) {
if (sharedState.dadMeatPermissionState != 0)
return playDadMeatPermissionConversion();
- return playDadLine(0x3a32);
+ return runtime.playDialogueLineWithVariant(0x3a32, "DAD", 0);
}
- return playDadLine(0x3a32);
+ return runtime.playDialogueLineWithVariant(0x3a32, "DAD", 0);
}
Common::Error lineError = Common::kNoError;
@@ -200,13 +188,12 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.dialogueStateD2ed0 = true;
state.introPending = false;
- lineError = playSequence(kDadIntroLines, ARRAYSIZE(kDadIntroLines));
+ lineError = runtime.playDialogueEntrySequence(kDadIntroLines, ARRAYSIZE(kDadIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
- lineError = playSequence(kDadIntroContinuationLines,
- ARRAYSIZE(kDadIntroContinuationLines));
+ lineError = runtime.playDialogueEntrySequence(kDadIntroContinuationLines, ARRAYSIZE(kDadIntroContinuationLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -214,7 +201,7 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(kDadOfferPromptLines, ARRAYSIZE(kDadOfferPromptLines));
+ lineError = runtime.playDialogueEntrySequence(kDadOfferPromptLines, ARRAYSIZE(kDadOfferPromptLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -226,17 +213,16 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(kDadOfferAcceptedLines,
- ARRAYSIZE(kDadOfferAcceptedLines));
+ lineError = runtime.playDialogueEntrySequence(kDadOfferAcceptedLines, ARRAYSIZE(kDadOfferAcceptedLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playDadLine(0x39e0);
+ lineError = runtime.playDialogueLineWithVariant(0x39e0, "DAD", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playSequence(kDadOfferClosingLines, ARRAYSIZE(kDadOfferClosingLines));
+ lineError = runtime.playDialogueEntrySequence(kDadOfferClosingLines, ARRAYSIZE(kDadOfferClosingLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -245,7 +231,7 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
} else {
- lineError = playSequence(kDadMeatPermissionUnavailableLines,
+ lineError = runtime.playDialogueEntrySequence(kDadMeatPermissionUnavailableLines,
ARRAYSIZE(kDadMeatPermissionUnavailableLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -254,12 +240,12 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDadLine(0x3a0f);
+ lineError = runtime.playDialogueLineWithVariant(0x3a0f, "DAD", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else {
- lineError = playDadLine(0x3a17);
+ lineError = runtime.playDialogueLineWithVariant(0x3a17, "DAD", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -281,9 +267,9 @@ Common::Error DadDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (isLodgeTopic(selectedTopic)) {
sharedState.discussedLodgeTopic = true;
- lineError = playSequence(kDadLodgeTopicLines, ARRAYSIZE(kDadLodgeTopicLines));
+ lineError = runtime.playDialogueEntrySequence(kDadLodgeTopicLines, ARRAYSIZE(kDadLodgeTopicLines));
} else {
- lineError = playDadLine(0x3a2c);
+ lineError = runtime.playDialogueLineWithVariant(0x3a2c, "DAD", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
diff --git a/engines/harvester/npc/dad_dialogue.h b/engines/harvester/npc/dad_dialogue.h
index 5b5a523fdf5..a058ed8c6f9 100644
--- a/engines/harvester/npc/dad_dialogue.h
+++ b/engines/harvester/npc/dad_dialogue.h
@@ -33,7 +33,6 @@ public:
bool meatPermissionState = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = DadRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/dark_woman_dialogue.cpp b/engines/harvester/npc/dark_woman_dialogue.cpp
index 87683429d43..5db88eb2139 100644
--- a/engines/harvester/npc/dark_woman_dialogue.cpp
+++ b/engines/harvester/npc/dark_woman_dialogue.cpp
@@ -28,7 +28,6 @@ namespace Harvester {
namespace {
-static const char *const kDarkWomanNpc = "DARK_WOMAN";
static const char *const kHandMirrorItemName = "HANDMIRROR";
static const char *const kInventoryOwnerName = "INVENTORY";
static const char *const kSetDarkWomanFlagActionTag = "SET_D_W_FLAG";
@@ -41,25 +40,18 @@ static const int kDarkWomanNeedsMirrorResponseLine = 0x4f;
} // End of namespace
-bool DarkWomanDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kDarkWomanNpc);
-}
-
Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &) {
- auto playDarkWomanLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kDarkWomanNpc, headVariant);
- };
auto queueDarkWomanMonsterfyTransition = [&]() {
InteractionResult interaction;
- if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy(kDarkWomanNpc)) {
+ if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy("DARK_WOMAN")) {
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
}
runtime.queueDialogueInteractionIfNeeded(interaction);
};
auto runDarkWomanMonsterfyBranch = [&]() -> Common::Error {
- Common::Error lineError = playDarkWomanLine(0x4ce2, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x4ce2, "DARK_WOMAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -67,7 +59,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
};
auto runMirrorRevealBranch = [&]() -> Common::Error {
- Common::Error lineError = playDarkWomanLine(0x4d03, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x4d03, "DARK_WOMAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -75,7 +67,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDarkWomanLine(0x4d0d, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x4d0d, "DARK_WOMAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -100,7 +92,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
_state.talkStatePending = false;
- Common::Error lineError = playDarkWomanLine(0x4cd5, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x4cd5, "DARK_WOMAN", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -115,7 +107,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex != 2)
return Common::kNoError;
- lineError = playDarkWomanLine(0x4ce6, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x4ce6, "DARK_WOMAN", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -130,7 +122,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex != 2)
return Common::kNoError;
- lineError = playDarkWomanLine(0x4ce6, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x4ce6, "DARK_WOMAN", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -145,7 +137,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex != 2)
return Common::kNoError;
- lineError = playDarkWomanLine(0x4ce6, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x4ce6, "DARK_WOMAN", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -160,7 +152,7 @@ Common::Error DarkWomanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 1)
return runDarkWomanMonsterfyBranch();
if (!hasHandMirror)
- return playDarkWomanLine(0x4cfc, 2);
+ return runtime.playDialogueLineWithVariant(0x4cfc, "DARK_WOMAN", 2);
return runMirrorRevealBranch();
}
diff --git a/engines/harvester/npc/dark_woman_dialogue.h b/engines/harvester/npc/dark_woman_dialogue.h
index 9351d9c15c6..eb3e3e00c6b 100644
--- a/engines/harvester/npc/dark_woman_dialogue.h
+++ b/engines/harvester/npc/dark_woman_dialogue.h
@@ -32,7 +32,6 @@ public:
bool talkStatePending = true;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = DarkWomanRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.talkStatePending);
diff --git a/engines/harvester/npc/dialogue_handler.h b/engines/harvester/npc/dialogue_handler.h
index d3c45f829ad..7877b7f7bbd 100644
--- a/engines/harvester/npc/dialogue_handler.h
+++ b/engines/harvester/npc/dialogue_handler.h
@@ -100,7 +100,6 @@ class NpcDialogueHandler {
public:
virtual ~NpcDialogueHandler() {}
- virtual bool matchesNpc(const Common::String &npcName) const = 0;
virtual void resetState() {}
virtual void syncState(Common::Serializer &) {}
virtual void migrateSharedState(DialogueSharedState &) {}
diff --git a/engines/harvester/npc/dialogue_runtime.h b/engines/harvester/npc/dialogue_runtime.h
index e04c53ab5f9..50b7ce3cfa2 100644
--- a/engines/harvester/npc/dialogue_runtime.h
+++ b/engines/harvester/npc/dialogue_runtime.h
@@ -78,6 +78,13 @@ public:
bool allowTransitions = true) const {
return _script.executeActionTag(tag, result, allowTransitions, _currentRoomName);
}
+ void executeAndQueueAction(const Common::String &tag) const {
+ InteractionResult interaction;
+ if (executeActionTag(tag, interaction)) {
+ applyImmediateDialogueInteractionEffects(interaction);
+ queueDialogueInteractionIfNeeded(interaction);
+ }
+ }
Common::Error playDialogueLineWithVariant(int wavId, const Common::String &speakerId,
int headVariant) const {
@@ -139,6 +146,27 @@ private:
mutable KeywordMenuSelectionState _lastKeywordSelection;
};
+class DialogueTopicBuffer {
+public:
+ DialogueTopicBuffer(const DialogueRuntime &runtime, Common::String &text, int &lineIndex,
+ const char *label)
+ : _runtime(runtime), _text(text), _lineIndex(lineIndex), _label(label) {}
+
+ void assign(int responseLineIndex) const {
+ _runtime.assignTopicBuffer(_text, _lineIndex, responseLineIndex, _label);
+ }
+ void clear() const {
+ _text.clear();
+ _lineIndex = -1;
+ }
+
+private:
+ const DialogueRuntime &_runtime;
+ Common::String &_text;
+ int &_lineIndex;
+ const char *_label;
+};
+
} // End of namespace Harvester
#endif // HARVESTER_NPC_DIALOGUE_RUNTIME_H
diff --git a/engines/harvester/npc/dwayne_dialogue.cpp b/engines/harvester/npc/dwayne_dialogue.cpp
index e2e465a3bbe..8df403f2f11 100644
--- a/engines/harvester/npc/dwayne_dialogue.cpp
+++ b/engines/harvester/npc/dwayne_dialogue.cpp
@@ -30,11 +30,6 @@ namespace Harvester {
namespace {
-static const char *const kDwayneNpc = "DWAYNE";
-static const char *const kDwayneDnaLeftNpc = "DWAYNE_DNALFT";
-static const char *const kDwayneStBedroomNpc = "DWAYNE_ST_BEDRM";
-static const char *const kEdnaNpc = "EDNA";
-static const char *const kPcSpeaker = "PC";
static const char *const kInventoryOwnerName = "INVENTORY";
static const char *const kRahRoomName = "RAH";
@@ -43,12 +38,6 @@ static const int kDwayneLoomisTopicResponseLines[] = { 0x8c, 0x8d };
} // End of namespace
-bool DwayneDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kDwayneNpc) ||
- npcName.equalsIgnoreCase(kDwayneDnaLeftNpc) ||
- npcName.equalsIgnoreCase(kDwayneStBedroomNpc);
-}
-
Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
DwayneRoomDialogueState &state = _state;
@@ -57,19 +46,8 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
int &dwayneTopicBufferLineIndex = state.currentTopicBufferLineIndex;
state.currentTopicBuffer.clear();
state.currentTopicBufferLineIndex = -1;
- auto assignDwayneTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(dwayneTopicBuffer, dwayneTopicBufferLineIndex,
- responseLineIndex, "Dwayne topic buffer");
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
- auto playDwayneLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kDwayneNpc, headVariant);
- };
- auto playEdnaLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kEdnaNpc, headVariant);
- };
+ DialogueTopicBuffer topics(runtime, dwayneTopicBuffer, dwayneTopicBufferLineIndex, "Dwayne topic buffer");
+
auto hideObjectIfPresent = [&](const char *ownerOrRoom, const Common::String &objectName) {
if (startupScript.isObjectInInventory(objectName))
(void)startupScript.setRuntimeObjectVisible(ownerOrRoom, objectName, false);
@@ -86,14 +64,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)startupScript.addRuntimeObjectToInventory("GOOJF_CARD");
(void)startupScript.setRuntimeFlagValue("PC_HAS_GOOJF_CARD", true);
};
- auto executeActionTagIfSet = [&](const char *tag) {
- InteractionResult interaction;
- if (!runtime.executeActionTag(tag, interaction))
- return;
- runtime.applyImmediateDialogueInteractionEffects(interaction);
- runtime.queueDialogueInteractionIfNeeded(interaction);
- };
auto setDwayneIntroduced = [&]() {
(void)startupScript.setRuntimeFlagValue("DWAYNE_INTRODUCED", true);
};
@@ -113,44 +84,44 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)startupScript.setRuntimeFlagValue("ARREST_FLAG", false);
if (startupScript.getFlagValue("PC_BUSTED_KILLED_MOYNAHAN")) {
- Common::Error lineError = playDwayneLine(0x38d6, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x38d6, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("PC_BUSTED_KILLED_MOYNAHAN", false);
} else if (startupScript.getFlagValue("PC_BUSTED_KILLED_JIMMY")) {
- Common::Error lineError = playDwayneLine(0x384d, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x384d, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("PC_BUSTED_KILLED_JIMMY", false);
(void)startupScript.setRuntimeFlagValue("KILLED_JIMMY", false);
} else if (startupScript.getFlagValue("PC_BUSTED_KILLED_JOHNSON")) {
- Common::Error lineError = playDwayneLine(0x386d, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x386d, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("PC_BUSTED_KILLED_JOHNSON", false);
} else if (startupScript.getFlagValue("PC_BUSTED_KILLED_PHELPS")) {
- Common::Error lineError = playDwayneLine(0x38bc, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x38bc, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("PC_BUSTED_KILLED_PHELPS", false);
} else if (startupScript.getFlagValue("PC_BUSTED_KILLED_OREILLY")) {
- Common::Error lineError = playDwayneLine(0x38b5, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x38b5, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("PC_BUSTED_KILLED_OREILLY", false);
(void)startupScript.setRuntimeFlagValue("KILLED_OREILLY", false);
} else if (startupScript.getFlagValue("IF_KILL_POTTSDAM_AT_GRAVE")) {
- Common::Error lineError = playDwayneLine(0x37ed, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x37ed, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("IF_KILL_POTTSDAM_AT_GRAVE", false);
} else if (startupScript.getFlagValue("GENERIC_BUST")) {
- Common::Error lineError = playDwayneLine(0x38fc, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x38fc, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("GENERIC_BUST", false);
} else if (startupScript.getFlagValue("DNALFT_PERVERT")) {
- Common::Error lineError = playDwayneLine(0x3580, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3580, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("DNALFT_PERVERT", false);
@@ -158,17 +129,17 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("PC_HAS_GOOJF_CARD") &&
!startupScript.getFlagValue("PC_FRY_IN_CHAIR")) {
- Common::Error lineError = playDwayneLine(0x3814);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3814, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (startupScript.getFlagValue("PC_KILLED_ANYONE")) {
const DialogueLineEntry goojfCardLines[] = {
- { 0x3820, kDwayneNpc, 0 },
- { 0x3824, kPcSpeaker, 0 },
- { 0x3828, kDwayneNpc, 0 }
+ { 0x3820, "DWAYNE", 0 },
+ { 0x3824, "PC", 0 },
+ { 0x3828, "DWAYNE", 0 }
};
- lineError = playSequence(goojfCardLines, ARRAYSIZE(goojfCardLines));
+ lineError = runtime.playDialogueEntrySequence(goojfCardLines, ARRAYSIZE(goojfCardLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -177,15 +148,15 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x3832, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x3832, "DWAYNE", 1);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x383b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x383b, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = runtime.playDialogueLineWithVariant(0x3840, kPcSpeaker, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x3840, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x3844, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3844, "DWAYNE", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -198,32 +169,32 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("PC_FRY_IN_CHAIR"))
return Common::kNoError;
if (startupScript.getFlagValue("BUSTED_THIRD"))
- return playDwayneLine(0x3928, 2);
+ return runtime.playDialogueLineWithVariant(0x3928, "DWAYNE", 2);
if (startupScript.getFlagValue("BUSTED_TWICE"))
- return playDwayneLine(0x3921, 2);
+ return runtime.playDialogueLineWithVariant(0x3921, "DWAYNE", 2);
if (startupScript.getFlagValue("BUSTED_ONCE"))
- return playDwayneLine(0x3918);
+ return runtime.playDialogueLineWithVariant(0x3918, "DWAYNE", 0);
return Common::kNoError;
}
if (startupScript.getFlagValue("CHECK_EVIDENCE_DOOR")) {
- Common::Error lineError = playDwayneLine(0x3386);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3386, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("CHECK_EVIDENCE_DOOR", false);
return Common::kNoError;
}
if (startupScript.getFlagValue("PC_TRIES_TO_TAKE_STEPHANIES_REMAINS"))
- return playDwayneLine(0x34e3, 2);
+ return runtime.playDialogueLineWithVariant(0x34e3, "DWAYNE", 2);
if (runtime.currentRoomName().equalsIgnoreCase("ST_BEDRM")) {
if (!startupScript.getFlagValue("SD_TALKED_OF_CARD")) {
- Common::Error lineError = playDwayneLine(0x34da);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x34da, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("SD_TALKED_OF_CARD", true);
return Common::kNoError;
}
- return playDwayneLine(0x3395);
+ return runtime.playDialogueLineWithVariant(0x3395, "DWAYNE", 0);
}
if (startupScript.getFlagValue("BRING_KARIN_TO_SHERIFF") &&
@@ -232,12 +203,12 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
setPendingKarinAliveFollowup();
state.bringKarinToSheriffLinePlayed = true;
const DialogueLineEntry lines[] = {
- { 0x3750, kDwayneNpc, 1 },
- { 0x3754, kPcSpeaker, 0 },
- { 0x3759, kDwayneNpc, 0 },
- { 0x375d, kDwayneNpc, 1 }
+ { 0x3750, "DWAYNE", 1 },
+ { 0x3754, "PC", 0 },
+ { 0x3759, "DWAYNE", 0 },
+ { 0x375d, "DWAYNE", 1 }
};
- return playSequence(lines, ARRAYSIZE(lines));
+ return runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
}
if (startupScript.getFlagValue("KARIN_FOUND_ALIVE"))
setPendingKarinAliveFollowup();
@@ -247,30 +218,30 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.discussedBoylesButton = true;
sharedState.dwayneDiscussedBoylesButton = true;
const DialogueLineEntry lines[] = {
- { 0x339b, kDwayneNpc, 0 },
- { 0x33a0, kPcSpeaker, 0 },
- { 0x33a5, kDwayneNpc, 0 },
- { 0x33a9, kPcSpeaker, 0 },
- { 0x33ad, kDwayneNpc, 2 }
+ { 0x339b, "DWAYNE", 0 },
+ { 0x33a0, "PC", 0 },
+ { 0x33a5, "DWAYNE", 0 },
+ { 0x33a9, "PC", 0 },
+ { 0x33ad, "DWAYNE", 2 }
};
- return playSequence(lines, ARRAYSIZE(lines));
+ return runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
}
if (usedItemName.equalsIgnoreCase("K_PURSE")) {
state.discussedKarinPurse = true;
sharedState.discussedKarinPurse = 1;
const DialogueLineEntry lines[] = {
- { 0x37cb, kDwayneNpc, 1 },
- { 0x37cf, kPcSpeaker, 3 },
- { 0x37b4, kDwayneNpc, 3 },
- { 0x37c1, kDwayneNpc, 0 },
- { 0x37c5, kPcSpeaker, 0 }
+ { 0x37cb, "DWAYNE", 1 },
+ { 0x37cf, "PC", 3 },
+ { 0x37b4, "DWAYNE", 3 },
+ { 0x37c1, "DWAYNE", 0 },
+ { 0x37c5, "PC", 0 }
};
- return playSequence(lines, ARRAYSIZE(lines));
+ return runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
}
if (usedItemName.equalsIgnoreCase("CHECKBOOK_PHOTOCOPY") ||
usedItemName.equalsIgnoreCase("NOTE_PHOTOCOPY")) {
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
- Common::Error lineError = playDwayneLine(0x33b9, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x33b9, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -279,17 +250,17 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x33c3, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x33c3, "DWAYNE", 2);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x33c7, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x33c7, "DWAYNE", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = runtime.playDialogueLineWithVariant(0x33cb, kPcSpeaker, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x33cb, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x33d2);
+ lineError = runtime.playDialogueLineWithVariant(0x33d2, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -298,15 +269,15 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x33e0);
+ lineError = runtime.playDialogueLineWithVariant(0x33e0, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
state.presentedEvidenceReplyOverride = true;
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x33e7, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x33e7, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
}
return Common::kNoError;
}
@@ -315,11 +286,11 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
if (state.presentedEvidenceReplyOverride) {
const DialogueLineEntry introLines[] = {
- { 0x342c, kDwayneNpc, 0 },
- { 0x3430, kPcSpeaker, 0 },
- { 0x3435, kDwayneNpc, 2 }
+ { 0x342c, "DWAYNE", 0 },
+ { 0x3430, "PC", 0 },
+ { 0x3435, "DWAYNE", 2 }
};
- Common::Error lineError = playSequence(introLines, ARRAYSIZE(introLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(introLines, ARRAYSIZE(introLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -328,14 +299,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x3440, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3440, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
return Common::kNoError;
}
if (responseIndex == 2) {
- lineError = playDwayneLine(0x3448);
+ lineError = runtime.playDialogueLineWithVariant(0x3448, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
confiscateSheriffEvidence();
@@ -344,7 +315,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
}
- Common::Error lineError = playDwayneLine(0x33f4, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x33f4, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -354,17 +325,17 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
lineError = Common::kNoError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x33c3, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x33c3, "DWAYNE", 2);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x3403, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3403, "DWAYNE", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = runtime.playDialogueLineWithVariant(0x3407, kPcSpeaker, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3407, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x340d);
+ lineError = runtime.playDialogueLineWithVariant(0x340d, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -375,17 +346,17 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 0)
return Common::kNoError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x341a);
+ lineError = runtime.playDialogueLineWithVariant(0x341a, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
return Common::kNoError;
}
if (responseIndex == 2) {
- lineError = playDwayneLine(0x3422, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3422, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
return Common::kNoError;
}
return Common::kNoError;
@@ -396,65 +367,65 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedLedgerEvidence = 1;
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownLedgersToAnyone, true);
const DialogueLineEntry lines[] = {
- { 0x3452, kDwayneNpc, 0 },
- { 0x3457, kPcSpeaker, 0 },
- { 0x345c, kDwayneNpc, 0 },
- { 0x3460, kPcSpeaker, 2 },
- { 0x3464, kDwayneNpc, 0 },
- { 0x346a, kPcSpeaker, 2 },
- { 0x346e, kDwayneNpc, 0 },
- { 0x3474, kPcSpeaker, 4 },
- { 0x3478, kDwayneNpc, 2 }
+ { 0x3452, "DWAYNE", 0 },
+ { 0x3457, "PC", 0 },
+ { 0x345c, "DWAYNE", 0 },
+ { 0x3460, "PC", 2 },
+ { 0x3464, "DWAYNE", 0 },
+ { 0x346a, "PC", 2 },
+ { 0x346e, "DWAYNE", 0 },
+ { 0x3474, "PC", 4 },
+ { 0x3478, "DWAYNE", 2 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.resetRuntimeObjectToInitialState("LEDGER");
(void)startupScript.resetRuntimeObjectToInitialState("LEDGER2");
- executeActionTagIfSet(sheriffInDiner ? "CALL_POLICE" : "LEDGER_BUST");
+ runtime.executeAndQueueAction(sheriffInDiner ? "CALL_POLICE" : "LEDGER_BUST");
return Common::kNoError;
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
const DialogueLineEntry lines[] = {
- { 0x3975, kDwayneNpc, 3 },
- { 0x3979, kPcSpeaker, 0 },
- { 0x397e, kDwayneNpc, 0 }
+ { 0x3975, "DWAYNE", 3 },
+ { 0x3979, "PC", 0 },
+ { 0x397e, "DWAYNE", 0 }
};
- return playSequence(lines, ARRAYSIZE(lines));
+ return runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
}
if (usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
sharedState.discussedCasketPhotoEvidence = 1;
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
- Common::Error lineError = playDwayneLine(0x3942, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3942, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2ec8) {
const DialogueLineEntry lines[] = {
- { 0x3949, kPcSpeaker, 0 },
- { 0x3950, kDwayneNpc, 0 },
- { 0x3955, kPcSpeaker, 4 },
- { 0x3959, kDwayneNpc, 1 },
- { 0x396d, kDwayneNpc, 0 }
+ { 0x3949, "PC", 0 },
+ { 0x3950, "DWAYNE", 0 },
+ { 0x3955, "PC", 4 },
+ { 0x3959, "DWAYNE", 1 },
+ { 0x396d, "DWAYNE", 0 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
hideObjectIfPresent(kInventoryOwnerName, usedItemName);
- executeActionTagIfSet("CALL_POLICE");
+ runtime.executeAndQueueAction("CALL_POLICE");
} else {
const DialogueLineEntry lines[] = {
- { 0x3961, kPcSpeaker, 0 },
- { 0x3967, kDwayneNpc, 0 },
- { 0x396d, kDwayneNpc, 0 }
+ { 0x3961, "PC", 0 },
+ { 0x3967, "DWAYNE", 0 },
+ { 0x396d, "DWAYNE", 0 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -466,11 +437,11 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownEvidenceSheriffOwns, true);
const DialogueLineEntry introLines[] = {
- { 0x3686, kDwayneNpc, 0 },
- { 0x368a, kPcSpeaker, 0 },
- { 0x3690, kDwayneNpc, 0 }
+ { 0x3686, "DWAYNE", 0 },
+ { 0x368a, "PC", 0 },
+ { 0x3690, "DWAYNE", 0 }
};
- Common::Error lineError = playSequence(introLines, ARRAYSIZE(introLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(introLines, ARRAYSIZE(introLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -479,14 +450,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x369b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x369b, "DWAYNE", 2);
} else if (responseIndex == 2) {
const DialogueLineEntry responseLines[] = {
- { 0x36a3, kDwayneNpc, 0 },
- { 0x36a8, kPcSpeaker, 2 },
- { 0x36ac, kDwayneNpc, 2 }
+ { 0x36a3, "DWAYNE", 0 },
+ { 0x36a8, "PC", 2 },
+ { 0x36ac, "DWAYNE", 2 }
};
- lineError = playSequence(responseLines, ARRAYSIZE(responseLines));
+ lineError = runtime.playDialogueEntrySequence(responseLines, ARRAYSIZE(responseLines));
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -497,12 +468,12 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (!usedItemName.equalsIgnoreCase("TV_DEED") &&
!usedItemName.equalsIgnoreCase("TV_DEED_PHOTOCOPY")) {
- return playDwayneLine(0x3935);
+ return runtime.playDialogueLineWithVariant(0x3935, "DWAYNE", 0);
}
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownEvidenceSheriffOwns, true);
- Common::Error lineError = playDwayneLine(0x3608);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3608, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -511,14 +482,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x3613);
+ lineError = runtime.playDialogueLineWithVariant(0x3613, "DWAYNE", 0);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x3618);
+ lineError = runtime.playDialogueLineWithVariant(0x3618, "DWAYNE", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x361c);
+ lineError = runtime.playDialogueLineWithVariant(0x361c, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -527,9 +498,9 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x3629, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3629, "DWAYNE", 2);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x362d);
+ lineError = runtime.playDialogueLineWithVariant(0x362d, "DWAYNE", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -540,18 +511,18 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (usedItemName.equalsIgnoreCase("TV_DEED")) {
const DialogueLineEntry deedLines[] = {
- { 0x363b, kDwayneNpc, 0 },
- { 0x3641, kPcSpeaker, 0 },
- { 0x3645, kDwayneNpc, 0 }
+ { 0x363b, "DWAYNE", 0 },
+ { 0x3641, "PC", 0 },
+ { 0x3645, "DWAYNE", 0 }
};
- lineError = playSequence(deedLines, ARRAYSIZE(deedLines));
+ lineError = runtime.playDialogueEntrySequence(deedLines, ARRAYSIZE(deedLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
return Common::kNoError;
}
if (responseIndex != 1) {
- lineError = playDwayneLine(0x367b, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x367b, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
hideObjectIfPresent(kRahRoomName, "TV_DEED_PHOTOCOPY");
@@ -559,11 +530,11 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
const DialogueLineEntry copyLines[] = {
- { 0x364e, kDwayneNpc, 0 },
- { 0x3656, kPcSpeaker, 0 },
- { 0x365b, kDwayneNpc, 0 }
+ { 0x364e, "DWAYNE", 0 },
+ { 0x3656, "PC", 0 },
+ { 0x365b, "DWAYNE", 0 }
};
- lineError = playSequence(copyLines, ARRAYSIZE(copyLines));
+ lineError = runtime.playDialogueEntrySequence(copyLines, ARRAYSIZE(copyLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -572,7 +543,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x3665);
+ lineError = runtime.playDialogueLineWithVariant(0x3665, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
state.tvDeedReplyOverride = true;
@@ -580,14 +551,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (responseIndex == 2) {
const DialogueLineEntry responseLines[] = {
- { 0x366b, kDwayneNpc, 3 },
- { 0x3670, kPcSpeaker, 2 },
- { 0x3674, kDwayneNpc, 2 }
+ { 0x366b, "DWAYNE", 3 },
+ { 0x3670, "PC", 2 },
+ { 0x3674, "DWAYNE", 2 }
};
- lineError = playSequence(responseLines, ARRAYSIZE(responseLines));
+ lineError = runtime.playDialogueEntrySequence(responseLines, ARRAYSIZE(responseLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
}
return Common::kNoError;
}
@@ -599,36 +570,36 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
setDwayneIntroduced();
const DialogueLineEntry introLines[] = {
- { 0x3482, kDwayneNpc, 1 },
- { 0x3486, kPcSpeaker, 0 },
- { 0x348b, kDwayneNpc, 1 },
- { 0x3490, kEdnaNpc, 0 }
+ { 0x3482, "DWAYNE", 1 },
+ { 0x3486, "PC", 0 },
+ { 0x348b, "DWAYNE", 1 },
+ { 0x3490, "EDNA", 0 }
};
- Common::Error lineError = playSequence(introLines, ARRAYSIZE(introLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(introLines, ARRAYSIZE(introLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (startupScript.getFlagValue("KARIN_KIDNAPED")) {
sharedState.karinKidnapedDialogueState = true;
- lineError = playEdnaLine(0x3496, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3496, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playDwayneLine(0x349b, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x349b, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (state.pendingInitialConversation) {
const DialogueLineEntry initialLines[] = {
- { 0x34a0, kPcSpeaker, 0 },
- { 0x34a4, kDwayneNpc, 1 }
+ { 0x34a0, "PC", 0 },
+ { 0x34a4, "DWAYNE", 1 }
};
- lineError = playSequence(initialLines, ARRAYSIZE(initialLines));
+ lineError = runtime.playDialogueEntrySequence(initialLines, ARRAYSIZE(initialLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
handledIntroOrRevisit = true;
}
else if (state.sheriffInDinerIntroPlayed && sheriffInDiner) {
- Common::Error lineError = playDwayneLine(0x34ac);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x34ac, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
handledIntroOrRevisit = true;
@@ -638,22 +609,22 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
setDwayneIntroduced();
const DialogueLineEntry initialLines[] = {
- { 0x3245, kDwayneNpc, 1 },
+ { 0x3245, "DWAYNE", 1 },
{ 0x324a, "LOOMIS", 1 },
- { 0x324e, kPcSpeaker, 0 },
- { 0x3252, kDwayneNpc, 0 }
+ { 0x324e, "PC", 0 },
+ { 0x3252, "DWAYNE", 0 }
};
- Common::Error lineError = playSequence(initialLines, ARRAYSIZE(initialLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(initialLines, ARRAYSIZE(initialLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x78);
+ topics.assign(0x78);
if (sharedState.boyleGascanApplicationState)
(void)startupScript.setRuntimeFlagValue("MOVE_SHERIFF", true);
handledIntroOrRevisit = true;
}
if (!handledIntroOrRevisit && state.eventFollowupGate) {
- Common::Error lineError = playDwayneLine(0x34d3, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x34d3, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -661,7 +632,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (sharedState.dwayneWhaleyDisciplineFollowupState &&
!state.whaleyDisciplineFollowupShown) {
state.whaleyDisciplineFollowupShown = true;
- Common::Error lineError = playDwayneLine(0x34b3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x34b3, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -671,13 +642,13 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
lineError = Common::kNoError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x34bf, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x34bf, "DWAYNE", 2);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x34c5, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x34c5, "DWAYNE", 1);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x34cb, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x34cb, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -685,20 +656,20 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (sharedState.discussedNoteCheckbookEvidence != 0 &&
!state.noteCheckbookFollowupShown) {
state.noteCheckbookFollowupShown = true;
- Common::Error lineError = playDwayneLine(0x355f, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x355f, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.discussedTvDeedEvidence != 0) {
const DialogueLineEntry lines[] = {
- { 0x3565, kDwayneNpc, 2 },
- { 0x356a, kDwayneNpc, 2 },
- { 0x356f, kPcSpeaker, 2 },
- { 0x3573, kDwayneNpc, 0 }
+ { 0x3565, "DWAYNE", 2 },
+ { 0x356a, "DWAYNE", 2 },
+ { 0x356f, "PC", 2 },
+ { 0x3573, "DWAYNE", 0 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet("PC_FRY_DADDY_1");
+ runtime.executeAndQueueAction("PC_FRY_DADDY_1");
return Common::kNoError;
}
}
@@ -707,14 +678,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("SCRATCHED_TUCKER") &&
!state.scratchedTuckerShown) {
state.scratchedTuckerShown = true;
- Common::Error lineError = playDwayneLine(0x358b, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x358b, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("BOLT_OF_CLOTH_TAKEN") &&
!state.boltOfClothTakenShown) {
state.boltOfClothTakenShown = true;
- Common::Error lineError = playDwayneLine(0x3594, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3594, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -722,26 +693,26 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.barberPoleStolenShown) {
state.barberPoleStolenShown = true;
const DialogueLineEntry lines[] = {
- { 0x359d, kDwayneNpc, 0 },
- { 0x35a4, kDwayneNpc, 0 },
- { 0x35ab, kDwayneNpc, 0 }
+ { 0x359d, "DWAYNE", 0 },
+ { 0x35a4, "DWAYNE", 0 },
+ { 0x35ab, "DWAYNE", 0 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("DINER_BURNED") &&
!state.dinerBurnedShown) {
state.dinerBurnedShown = true;
- Common::Error lineError = playDwayneLine(0x35bc, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x35bc, "DWAYNE", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (startupScript.getFlagValue("KARIN_FOUND_ALIVE")) {
const DialogueLineEntry lines[] = {
- { 0x35c1, kDwayneNpc, 3 },
- { 0x35c5, kDwayneNpc, 3 }
+ { 0x35c1, "DWAYNE", 3 },
+ { 0x35c5, "DWAYNE", 3 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -749,14 +720,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("PC_ESCAPED_JAIL") &&
!state.escapedJailShown) {
state.escapedJailShown = true;
- Common::Error lineError = playDwayneLine(0x35cd);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x35cd, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("GOT_REMAINS_FOR_LODGE") &&
!state.gotRemainsForLodgeShown) {
state.gotRemainsForLodgeShown = true;
- Common::Error lineError = playDwayneLine(0x35d7);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x35d7, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -764,18 +735,18 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
const DialogueLineEntry lines[] = {
- { 0x35f6, kDwayneNpc, 2 },
- { 0x35fb, kDwayneNpc, 2 },
- { 0x3601, kDwayneNpc, 2 }
+ { 0x35f6, "DWAYNE", 2 },
+ { 0x35fb, "DWAYNE", 2 },
+ { 0x3601, "DWAYNE", 2 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("KARIN_KIDNAPED") &&
!state.karinKidnapedShown) {
state.karinKidnapedShown = true;
- Common::Error lineError = playDwayneLine(0x36b2, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x36b2, "DWAYNE", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.karinKidnapedDialogueState = true;
@@ -785,14 +756,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x36bd);
+ lineError = runtime.playDialogueLineWithVariant(0x36bd, "DWAYNE", 0);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x36c1);
+ lineError = runtime.playDialogueLineWithVariant(0x36c1, "DWAYNE", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x36c5);
+ lineError = runtime.playDialogueLineWithVariant(0x36c5, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -801,14 +772,14 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x36d0);
+ lineError = runtime.playDialogueLineWithVariant(0x36d0, "DWAYNE", 0);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x36d6, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x36d6, "DWAYNE", 1);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x36e7, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x36e7, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -822,11 +793,11 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.dwaynePendingKarinAliveFollowupState = 0;
const DialogueLineEntry lines[] = {
- { 0x3780, kDwayneNpc, 0 },
- { 0x3786, kPcSpeaker, 4 },
- { 0x378a, kDwayneNpc, 2 }
+ { 0x3780, "DWAYNE", 0 },
+ { 0x3786, "PC", 4 },
+ { 0x378a, "DWAYNE", 2 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
state.completedKarinAliveFollowup = true;
@@ -839,7 +810,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!sheriffInDiner &&
!state.karinFoundDeadWithoutPurseShown) {
state.karinFoundDeadWithoutPurseShown = true;
- Common::Error lineError = playDwayneLine(0x3793);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3793, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -848,9 +819,9 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- return playDwayneLine(0x379d);
+ return runtime.playDialogueLineWithVariant(0x379d, "DWAYNE", 0);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x37a4, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x37a4, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -859,18 +830,18 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x37ae);
+ lineError = runtime.playDialogueLineWithVariant(0x37ae, "DWAYNE", 0);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x37b4, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x37b4, "DWAYNE", 3);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
const DialogueLineEntry lines[] = {
- { 0x37c1, kDwayneNpc, 0 },
- { 0x37c5, kPcSpeaker, 0 }
+ { 0x37c1, "DWAYNE", 0 },
+ { 0x37c5, "PC", 0 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -880,11 +851,11 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!sheriffInDiner &&
!state.jimmyAbsentShown) {
state.jimmyAbsentShown = true;
- Common::Error lineError = playDwayneLine(0x3855, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3855, "DWAYNE", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (startupScript.getFlagValue("JIMMY_ATTACKED")) {
- lineError = playDwayneLine(0x37f8);
+ lineError = runtime.playDialogueLineWithVariant(0x37f8, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -894,9 +865,9 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
lineError = Common::kNoError;
if (responseIndex == 1) {
- lineError = playDwayneLine(0x3805, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x3805, "DWAYNE", 1);
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x380c);
+ lineError = runtime.playDialogueLineWithVariant(0x380c, "DWAYNE", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -907,7 +878,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!sheriffInDiner &&
!state.moynahanAbsentShown) {
state.moynahanAbsentShown = true;
- Common::Error lineError = playDwayneLine(0x38ce);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x38ce, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -915,7 +886,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("EDNA_HUNG") &&
!state.ednaHungShown) {
state.ednaHungShown = true;
- Common::Error lineError = playDwayneLine(0x38f1, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x38f1, "DWAYNE", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -925,8 +896,8 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.mcknightAbsentShown) {
state.mcknightAbsentShown = true;
Common::Error lineError = startupScript.isObjectInInventory("TV_DEED")
- ? playDwayneLine(0x3904, 3)
- : playDwayneLine(0x390f, 1);
+ ? runtime.playDialogueLineWithVariant(0x3904, "DWAYNE", 3)
+ : runtime.playDialogueLineWithVariant(0x390f, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -934,7 +905,7 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
Common::String selectedTopic;
for (;;) {
if (runtime.matchesResponseLine(selectedTopic, 0x82))
- return playDwayneLine(0x3395);
+ return runtime.playDialogueLineWithVariant(0x3395, "DWAYNE", 0);
Common::Error menuError = runtime.runKeywordMenu(
dwayneTopicBuffer, dwayneTopicBufferLineIndex, selectedTopic);
@@ -944,10 +915,10 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
if (runtime.matchesResponseLine(selectedTopic, 0x83)) {
- Common::Error lineError = playDwayneLine(0x326e);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x326e, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x84);
+ topics.assign(0x84);
continue;
}
@@ -955,20 +926,20 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
ARRAYSIZE(kDwayneWhaleyTopicResponseLines))) {
if (!sheriffInDiner) {
const DialogueLineEntry lines[] = {
- { 0x327b, kDwayneNpc, 0 },
- { 0x3280, kPcSpeaker, 2 },
- { 0x3285, kDwayneNpc, 0 },
+ { 0x327b, "DWAYNE", 0 },
+ { 0x3280, "PC", 2 },
+ { 0x3285, "DWAYNE", 0 },
{ 0x328b, "LOOMIS", 1 },
- { 0x3290, kDwayneNpc, 2 },
+ { 0x3290, "DWAYNE", 2 },
{ 0x3294, "LOOMIS", 3 },
- { 0x3299, kPcSpeaker, 4 },
- { 0x329e, kDwayneNpc, 1 }
+ { 0x3299, "PC", 4 },
+ { 0x329e, "DWAYNE", 1 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
- assignDwayneTopicBuffer(0x89);
+ topics.assign(0x89);
}
continue;
}
@@ -977,46 +948,46 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
ARRAYSIZE(kDwayneLoomisTopicResponseLines))) {
if (!sheriffInDiner) {
const DialogueLineEntry lines[] = {
- { 0x32bf, kDwayneNpc, 1 },
- { 0x32c1, kDwayneNpc, 0 },
+ { 0x32bf, "DWAYNE", 1 },
+ { 0x32c1, "DWAYNE", 0 },
{ 0x32c7, "LOOMIS", 3 },
- { 0x32cb, kDwayneNpc, 0 },
+ { 0x32cb, "DWAYNE", 0 },
{ 0x32d1, "LOOMIS", 1 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- runtime.setActiveSpeakerPortrait(kDwayneNpc, 0);
- assignDwayneTopicBuffer(0x8e);
+ runtime.setActiveSpeakerPortrait("DWAYNE", 0);
+ topics.assign(0x8e);
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x8f)) {
const DialogueLineEntry lines[] = {
- { 0x32db, kDwayneNpc, 0 },
- { 0x32e2, kPcSpeaker, 4 },
- { 0x32e6, kDwayneNpc, 0 }
+ { 0x32db, "DWAYNE", 0 },
+ { 0x32e2, "PC", 4 },
+ { 0x32e6, "DWAYNE", 0 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x90);
+ topics.assign(0x90);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x91)) {
const DialogueLineEntry lines[] = {
- { 0x32f2, kDwayneNpc, 0 },
- { 0x32f9, kPcSpeaker, 0 },
- { 0x32fd, kDwayneNpc, 0 },
- { 0x32fe, kDwayneNpc, 0 },
- { 0x32ff, kDwayneNpc, 0 }
+ { 0x32f2, "DWAYNE", 0 },
+ { 0x32f9, "PC", 0 },
+ { 0x32fd, "DWAYNE", 0 },
+ { 0x32fe, "DWAYNE", 0 },
+ { 0x32ff, "DWAYNE", 0 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x92);
+ topics.assign(0x92);
continue;
}
@@ -1024,30 +995,30 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
Common::Error lineError = Common::kNoError;
if (!startupScript.getFlagValue("STEPH_MIDGAME_PLAYED")) {
const DialogueLineEntry lines[] = {
- { 0x330d, kDwayneNpc, 1 },
- { 0x3314, kPcSpeaker, 0 },
- { 0x3318, kDwayneNpc, 0 },
- { 0x332c, kDwayneNpc, 0 }
+ { 0x330d, "DWAYNE", 1 },
+ { 0x3314, "PC", 0 },
+ { 0x3318, "DWAYNE", 0 },
+ { 0x332c, "DWAYNE", 0 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
} else {
const DialogueLineEntry lines[] = {
- { 0x331f, kDwayneNpc, 3 },
- { 0x3320, kDwayneNpc, 0 },
- { 0x3321, kDwayneNpc, 0 },
- { 0x332c, kDwayneNpc, 0 }
+ { 0x331f, "DWAYNE", 3 },
+ { 0x3320, "DWAYNE", 0 },
+ { 0x3321, "DWAYNE", 0 },
+ { 0x332c, "DWAYNE", 0 }
};
- lineError = playSequence(lines, ARRAYSIZE(lines));
+ lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x94);
+ topics.assign(0x94);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x95)) {
sharedState.discussedLodgeTopic = true;
- Common::Error lineError = playDwayneLine(0x3339, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3339, "DWAYNE", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1058,65 +1029,65 @@ Common::Error DwayneDialogueHandler::handleDialogue(DialogueRuntime &runtime,
lineError = Common::kNoError;
if (responseIndex == 1) {
const DialogueLineEntry responseLines[] = {
- { 0x3345, kDwayneNpc, 2 },
- { 0x3346, kDwayneNpc, 2 },
- { 0x3347, kDwayneNpc, 2 }
+ { 0x3345, "DWAYNE", 2 },
+ { 0x3346, "DWAYNE", 2 },
+ { 0x3347, "DWAYNE", 2 }
};
- lineError = playSequence(responseLines, ARRAYSIZE(responseLines));
+ lineError = runtime.playDialogueEntrySequence(responseLines, ARRAYSIZE(responseLines));
} else if (responseIndex == 2) {
- lineError = playDwayneLine(0x3350);
+ lineError = runtime.playDialogueLineWithVariant(0x3350, "DWAYNE", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x97);
+ topics.assign(0x97);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x98)) {
const DialogueLineEntry lines[] = {
- { 0x335b, kDwayneNpc, 2 },
- { 0x3360, kPcSpeaker, 2 },
- { 0x3364, kDwayneNpc, 3 }
+ { 0x335b, "DWAYNE", 2 },
+ { 0x3360, "PC", 2 },
+ { 0x3364, "DWAYNE", 3 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = sharedState.dialogueStateD2f04
- ? runtime.playDialogueLineWithVariant(0x3368, kPcSpeaker, 2)
- : runtime.playDialogueLineWithVariant(0x336c, kPcSpeaker, 2);
+ ? runtime.playDialogueLineWithVariant(0x3368, "PC", 2)
+ : runtime.playDialogueLineWithVariant(0x336c, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDwayneLine(0x3370, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3370, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x99);
+ topics.assign(0x99);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x9a)) {
- Common::Error lineError = playDwayneLine(0x337a, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x337a, "DWAYNE", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x9b);
+ topics.assign(0x9b);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x9c)) {
const DialogueLineEntry lines[] = {
- { 0x3386, kDwayneNpc, 0 },
- { 0x3387, kDwayneNpc, 0 }
+ { 0x3386, "DWAYNE", 0 },
+ { 0x3387, "DWAYNE", 0 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignDwayneTopicBuffer(0x9d);
+ topics.assign(0x9d);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x9e))
continue;
- Common::Error lineError = playDwayneLine(0x393c);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x393c, "DWAYNE", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/dwayne_dialogue.h b/engines/harvester/npc/dwayne_dialogue.h
index a5106960d8e..fad96e2169a 100644
--- a/engines/harvester/npc/dwayne_dialogue.h
+++ b/engines/harvester/npc/dwayne_dialogue.h
@@ -61,7 +61,6 @@ public:
int currentTopicBufferLineIndex = -1;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = DwayneRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.pendingInitialConversation);
diff --git a/engines/harvester/npc/edna_dialogue.cpp b/engines/harvester/npc/edna_dialogue.cpp
index 8c569f376d4..6ee0d30fa0a 100644
--- a/engines/harvester/npc/edna_dialogue.cpp
+++ b/engines/harvester/npc/edna_dialogue.cpp
@@ -29,8 +29,6 @@ namespace Harvester {
namespace {
-static const char *const kEdnaNpc = "EDNA";
-static const char *const kPcSpeaker = "PC";
static const char *const kRahRoomName = "RAH";
static const char *const kDialogueC043FstPath = "GRAPHIC/FST/C043.FST";
static const char *const kDialogueC043KFstPath = "GRAPHIC/FST/C043K.FST";
@@ -49,65 +47,61 @@ static const int kEdnaLodgeTopicLineIndices[] = { 0xb6, 0xb7 };
static const int kEdnaBcBdBeTopicLineIndices[] = { 0xbc, 0xbd, 0xbe };
static const DialogueLineEntry kEdnaBringKarinToSheriffLines[] = {
- { 0x3cce, kEdnaNpc, 2 },
- { 0x3cd2, kPcSpeaker, 0 },
- { 0x3cd7, kEdnaNpc, 1 }
+ { 0x3cce, "EDNA", 2 },
+ { 0x3cd2, "PC", 0 },
+ { 0x3cd7, "EDNA", 1 }
};
static const DialogueLineEntry kEdnaIntroResponseTwoLines[] = {
- { 0x3ab2, kEdnaNpc, 0 },
- { 0x3ab7, kPcSpeaker, 0 },
- { 0x3abb, kEdnaNpc, 0 },
- { 0x3ac2, kPcSpeaker, 0 }
+ { 0x3ab2, "EDNA", 0 },
+ { 0x3ab7, "PC", 0 },
+ { 0x3abb, "EDNA", 0 },
+ { 0x3ac2, "PC", 0 }
};
static const DialogueLineEntry kEdnaDayFiveAliveResponseOneLines[] = {
- { 0x3c23, kEdnaNpc, 0 },
- { 0x3c29, kPcSpeaker, 0 },
- { 0x3c2e, kEdnaNpc, 3 }
+ { 0x3c23, "EDNA", 0 },
+ { 0x3c29, "PC", 0 },
+ { 0x3c2e, "EDNA", 3 }
};
static const DialogueLineEntry kEdnaBarberPoleStolenLines[] = {
- { 0x3c4e, kEdnaNpc, 3 },
- { 0x3c54, kPcSpeaker, 0 },
- { 0x3c5a, kEdnaNpc, 2 }
+ { 0x3c4e, "EDNA", 3 },
+ { 0x3c54, "PC", 0 },
+ { 0x3c5a, "EDNA", 2 }
};
static const DialogueLineEntry kEdnaKarinFoundDeadIntroLines[] = {
- { 0x3cf0, kEdnaNpc, 2 },
- { 0x3cf5, kPcSpeaker, 0 },
- { 0x3cf9, kEdnaNpc, 2 }
+ { 0x3cf0, "EDNA", 2 },
+ { 0x3cf5, "PC", 0 },
+ { 0x3cf9, "EDNA", 2 }
};
static const DialogueLineEntry kEdnaTopicB2Lines[] = {
- { 0x3b15, kEdnaNpc, 1 },
- { 0x3b1a, kPcSpeaker, 0 },
- { 0x3b1e, kEdnaNpc, 0 }
+ { 0x3b15, "EDNA", 1 },
+ { 0x3b1a, "PC", 0 },
+ { 0x3b1e, "EDNA", 0 }
};
static const DialogueLineEntry kEdnaLodgeTopicLines[] = {
- { 0x3b57, kEdnaNpc, 0 },
- { 0x3b5d, kPcSpeaker, 0 },
- { 0x3b61, kEdnaNpc, 0 },
- { 0x3b62, kEdnaNpc, 0 },
- { 0x3b63, kEdnaNpc, 0 },
- { 0x3b6c, kPcSpeaker, 0 },
- { 0x3b70, kEdnaNpc, 0 },
- { 0x3b75, kPcSpeaker, 0 },
- { 0x3b79, kEdnaNpc, 0 }
+ { 0x3b57, "EDNA", 0 },
+ { 0x3b5d, "PC", 0 },
+ { 0x3b61, "EDNA", 0 },
+ { 0x3b62, "EDNA", 0 },
+ { 0x3b63, "EDNA", 0 },
+ { 0x3b6c, "PC", 0 },
+ { 0x3b70, "EDNA", 0 },
+ { 0x3b75, "PC", 0 },
+ { 0x3b79, "EDNA", 0 }
};
static const DialogueLineEntry kEdnaTopicBcBdBeLines[] = {
- { 0x3b8e, kEdnaNpc, 0 },
- { 0x3b8f, kEdnaNpc, 0 }
+ { 0x3b8e, "EDNA", 0 },
+ { 0x3b8f, "EDNA", 0 }
};
} // End of namespace
-bool EdnaDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kEdnaNpc);
-}
-
Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
EdnaRoomDialogueState &state = _state;
@@ -115,19 +109,11 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
Common::String topicBuffer;
int topicBufferLineIndex = -1;
- auto assignEdnaTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(topicBuffer, topicBufferLineIndex,
- responseLineIndex, "Edna topic buffer");
- };
- auto playEdnaLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kEdnaNpc, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+ DialogueTopicBuffer topics(runtime, topicBuffer, topicBufferLineIndex, "Edna topic buffer");
+
auto completeKarinPurseExchange = [&]() -> Common::Error {
state.karinPurseLinePlayed = true;
- Common::Error lineError = playEdnaLine(0x3d05, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3d05, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -137,7 +123,7 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
};
if (startupScript.getFlagValue("KILLED_KARIN1")) {
- Common::Error lineError = playEdnaLine(0x3cdf, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3cdf, "EDNA", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)startupScript.setRuntimeFlagValue("KILLED_KARIN1", false);
@@ -166,19 +152,19 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
sharedState.discussedCasketPhotoEvidence = 1;
- return playEdnaLine(0x3bd6);
+ return runtime.playDialogueLineWithVariant(0x3bd6, "EDNA", 0);
}
if ((usedItemName.equalsIgnoreCase("LEDGER") ||
usedItemName.equalsIgnoreCase("LEDGER2")) &&
startupScript.getFlagValue("HAVE_BOTH_LEDGERS")) {
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownLedgersToAnyone, true);
sharedState.discussedLedgerEvidence = 1;
- return playEdnaLine(0x3bd6);
+ return runtime.playDialogueLineWithVariant(0x3bd6, "EDNA", 0);
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
sharedState.discussedWhaleyHerrillPhoto = 1;
- return playEdnaLine(0x3bde, 2);
+ return runtime.playDialogueLineWithVariant(0x3bde, "EDNA", 2);
}
if (usedItemName.equalsIgnoreCase("NOTE") ||
usedItemName.equalsIgnoreCase("NOTE_PHOTOCOPY") ||
@@ -186,21 +172,21 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CHECKBOOK_PHOTOCOPY")) {
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
sharedState.discussedNoteCheckbookEvidence = 1;
- return playEdnaLine(0x3be5, 2);
+ return runtime.playDialogueLineWithVariant(0x3be5, "EDNA", 2);
}
if (usedItemName.equalsIgnoreCase("TV_DEED") ||
usedItemName.equalsIgnoreCase("TV_DEED_PHOTOCOPY")) {
(void)startupScript.setRuntimeFlagValue(DialogueFlags::kShownEvidenceSheriffOwns, true);
sharedState.discussedTvDeedEvidence = 1;
- return playEdnaLine(0x3bee);
+ return runtime.playDialogueLineWithVariant(0x3bee, "EDNA", 0);
}
- return playEdnaLine(0x3bcf);
+ return runtime.playDialogueLineWithVariant(0x3bcf, "EDNA", 0);
}
if (startupScript.getFlagValue("BRING_KARIN_TO_SHERIFF")) {
- Common::Error lineError = playSequence(
- kEdnaBringKarinToSheriffLines, ARRAYSIZE(kEdnaBringKarinToSheriffLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kEdnaBringKarinToSheriffLines,
+ ARRAYSIZE(kEdnaBringKarinToSheriffLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -211,7 +197,7 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (state.introPending) {
state.introPending = false;
- Common::Error lineError = playEdnaLine(0x3a95);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3a95, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -221,44 +207,44 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playEdnaLine(0x3aa1, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x3aa1, "EDNA", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueLine(0x3aa6, "PC");
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playEdnaLine(0x3aaa);
+ lineError = runtime.playDialogueLineWithVariant(0x3aaa, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
- lineError = runtime.playDialogueLine(0x3aae, kPcSpeaker);
+ lineError = runtime.playDialogueLine(0x3aae, "PC");
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playSequence(kEdnaIntroResponseTwoLines, ARRAYSIZE(kEdnaIntroResponseTwoLines));
+ lineError = runtime.playDialogueEntrySequence(kEdnaIntroResponseTwoLines, ARRAYSIZE(kEdnaIntroResponseTwoLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playEdnaLine(0x3ac6, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3ac6, "EDNA", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playEdnaLine(0x3aca);
+ lineError = runtime.playDialogueLineWithVariant(0x3aca, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playEdnaLine(0x3acf);
+ lineError = runtime.playDialogueLineWithVariant(0x3acf, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(kEdnaInitialTopicBufferLine);
+ topics.assign(kEdnaInitialTopicBufferLine);
}
if (!startupScript.getFlagValue("KARIN_KIDNAPED")) {
- Common::Error lineError = playEdnaLine(0x3bf8);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3bf8, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else {
- Common::Error lineError = playEdnaLine(0x3bff);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3bff, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.karinKidnapedDialogueState = true;
@@ -267,7 +253,7 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("DAY_5") && !state.dayFiveShown) {
state.dayFiveShown = true;
if (startupScript.getFlagValue("KARIN_FOUND_ALIVE")) {
- Common::Error lineError = playEdnaLine(0x3c17);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3c17, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -277,17 +263,17 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(kEdnaDayFiveAliveResponseOneLines,
+ lineError = runtime.playDialogueEntrySequence(kEdnaDayFiveAliveResponseOneLines,
ARRAYSIZE(kEdnaDayFiveAliveResponseOneLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playEdnaLine(0x3c33);
+ lineError = runtime.playDialogueLineWithVariant(0x3c33, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else if (startupScript.getFlagValue("KARIN_FOUND_DEAD")) {
- Common::Error lineError = playEdnaLine(0x3c3a, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3c3a, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -295,43 +281,43 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (startupScript.getFlagValue("SCRATCHED_TUCKER") && !state.scratchedTuckerShown) {
state.scratchedTuckerShown = true;
- Common::Error lineError = playEdnaLine(0x3c45);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3c45, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("BARBER_POLE_STOLEN") &&
!state.barberPoleStolenShown) {
state.barberPoleStolenShown = true;
- Common::Error lineError = playSequence(
- kEdnaBarberPoleStolenLines, ARRAYSIZE(kEdnaBarberPoleStolenLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kEdnaBarberPoleStolenLines,
+ ARRAYSIZE(kEdnaBarberPoleStolenLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("BOLT_OF_CLOTH_TAKEN") &&
!state.boltOfClothTakenShown) {
state.boltOfClothTakenShown = true;
- Common::Error lineError = playEdnaLine(0x3c62);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3c62, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("PC_ESCAPED_JAIL") &&
!state.escapedJailShown) {
state.escapedJailShown = true;
- Common::Error lineError = playEdnaLine(0x3c92, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3c92, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("BURNED_TV_STATION") &&
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
- Common::Error lineError = playEdnaLine(0x3ca2, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3ca2, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (startupScript.getFlagValue("KARIN_FOUND_DEAD") &&
!state.karinFoundDeadShown) {
state.karinFoundDeadShown = true;
- Common::Error lineError = playEdnaLine(0x3ce5, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3ce5, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -341,8 +327,8 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(
- kEdnaKarinFoundDeadIntroLines, ARRAYSIZE(kEdnaKarinFoundDeadIntroLines));
+ lineError = runtime.playDialogueEntrySequence(kEdnaKarinFoundDeadIntroLines,
+ ARRAYSIZE(kEdnaKarinFoundDeadIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -364,12 +350,12 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return lineError;
}
} else if (responseIndex == 2) {
- lineError = playEdnaLine(0x3d0a, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3d0a, "EDNA", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else if (responseIndex == 2) {
- lineError = playEdnaLine(0x3d0e, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3d0e, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -389,7 +375,7 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!startupScript.getFlagValue("KARIN_KIDNAPED") &&
!startupScript.getFlagValue("KARIN_FOUND_DEAD") &&
!startupScript.getFlagValue("KARIN_FOUND_ALIVE")) {
- Common::Error lineError = playEdnaLine(0x3bc3, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3bc3, "EDNA", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -399,22 +385,21 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0xa6)) {
if (!startupScript.getFlagValue("KARIN_KIDNAPED") &&
!startupScript.getFlagValue("KARIN_FOUND_DEAD")) {
- Common::Error lineError = playEdnaLine(0x3ad9, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3ad9, "EDNA", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC091FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else {
- Common::Error lineError = playEdnaLine(0x3ae3, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3ae3, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!startupScript.getFlagValue("KARIN_FOUND_DEAD")) {
- lineError = playEdnaLine(0x3ae9, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3ae9, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(
- startupScript.getFlagValue("SHERIFF_IN_DINER") ? 0xab : 0xaa);
+ topics.assign(startupScript.getFlagValue("SHERIFF_IN_DINER") ? 0xab : 0xaa);
}
}
continue;
@@ -422,31 +407,31 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kEdnaAcAdTopicLineIndices,
ARRAYSIZE(kEdnaAcAdTopicLineIndices))) {
- Common::Error lineError = playEdnaLine(0x3af6);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3af6, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playEdnaLine(0x3af8);
+ lineError = runtime.playDialogueLineWithVariant(0x3af8, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(startupScript.getFlagValue("SHERIFF_IN_DINER") ? 0xaf : 0xae);
+ topics.assign(startupScript.getFlagValue("SHERIFF_IN_DINER") ? 0xaf : 0xae);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xb0)) {
if (!startupScript.getFlagValue("SHERIFF_IN_DINER")) {
- Common::Error lineError = playEdnaLine(0x3b03);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3b03, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playEdnaLine(0x3b07);
+ lineError = runtime.playDialogueLineWithVariant(0x3b07, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(0xb1);
+ topics.assign(0xb1);
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xb2)) {
- Common::Error lineError = playSequence(kEdnaTopicB2Lines, ARRAYSIZE(kEdnaTopicB2Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kEdnaTopicB2Lines, ARRAYSIZE(kEdnaTopicB2Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
@@ -455,19 +440,19 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kEdnaLodgeTopicLineIndices,
ARRAYSIZE(kEdnaLodgeTopicLineIndices))) {
sharedState.discussedLodgeTopic = true;
- Common::Error lineError = playSequence(kEdnaLodgeTopicLines, ARRAYSIZE(kEdnaLodgeTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kEdnaLodgeTopicLines, ARRAYSIZE(kEdnaLodgeTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(startupScript.getFlagValue("SHERIFF_IN_DINER") ? 0xb9 : 0xb8);
+ topics.assign(startupScript.getFlagValue("SHERIFF_IN_DINER") ? 0xb9 : 0xb8);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xba)) {
if (!startupScript.getFlagValue("SHERIFF_IN_DINER")) {
- Common::Error lineError = playEdnaLine(0x3b82);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3b82, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(0xbb);
+ topics.assign(0xbb);
}
continue;
}
@@ -475,18 +460,18 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kEdnaBcBdBeTopicLineIndices,
ARRAYSIZE(kEdnaBcBdBeTopicLineIndices))) {
if (!startupScript.getFlagValue("SHERIFF_IN_DINER")) {
- Common::Error lineError = playSequence(
- kEdnaTopicBcBdBeLines, ARRAYSIZE(kEdnaTopicBcBdBeLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kEdnaTopicBcBdBeLines,
+ ARRAYSIZE(kEdnaTopicBcBdBeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignEdnaTopicBuffer(0xbf);
+ topics.assign(0xbf);
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xc0)) {
if (startupScript.getFlagValue("KARIN_KIDNAPED")) {
- Common::Error lineError = playEdnaLine(0x3b9e, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3b9e, "EDNA", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.karinKidnapedDialogueState = true;
@@ -496,7 +481,7 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
- lineError = playEdnaLine(responseIndex == 1 ? 0x3bad : 0x3bb3, 3);
+ lineError = runtime.playDialogueLineWithVariant(responseIndex == 1 ? 0x3bad : 0x3bb3, "EDNA", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC070FstPath);
@@ -510,7 +495,7 @@ Common::Error EdnaDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0xc2))
continue;
- Common::Error lineError = playEdnaLine(0x3bc9);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3bc9, "EDNA", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/edna_dialogue.h b/engines/harvester/npc/edna_dialogue.h
index 5db136900d3..a83f447de60 100644
--- a/engines/harvester/npc/edna_dialogue.h
+++ b/engines/harvester/npc/edna_dialogue.h
@@ -40,7 +40,6 @@ public:
bool karinFoundDeadShown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = EdnaRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/fireman1_dialogue.cpp b/engines/harvester/npc/fireman1_dialogue.cpp
index f6812ff0ee8..46bacf2effa 100644
--- a/engines/harvester/npc/fireman1_dialogue.cpp
+++ b/engines/harvester/npc/fireman1_dialogue.cpp
@@ -26,16 +26,6 @@
namespace Harvester {
-namespace {
-
-static const char *const kFireman1Npc = "FIREMAN1";
-
-} // End of namespace
-
-bool Fireman1DialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kFireman1Npc);
-}
-
Common::Error Fireman1DialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
Fireman1RoomDialogueState &state = _state;
@@ -43,9 +33,9 @@ Common::Error Fireman1DialogueHandler::handleDialogue(DialogueRuntime &runtime,
Common::Error lineError = Common::kNoError;
if (state.talkStatePending) {
state.talkStatePending = false;
- lineError = runtime.playDialogueLine(0x453, kFireman1Npc);
+ lineError = runtime.playDialogueLine(0x453, "FIREMAN1");
} else {
- lineError = runtime.playDialogueLine(0x463, kFireman1Npc);
+ lineError = runtime.playDialogueLine(0x463, "FIREMAN1");
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -53,7 +43,7 @@ Common::Error Fireman1DialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephMidgamePlayedShown) {
state.stephMidgamePlayedShown = true;
- lineError = runtime.playDialogueLineWithVariant(0x45a, kFireman1Npc, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x45a, "FIREMAN1", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -61,7 +51,7 @@ Common::Error Fireman1DialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("BOLT_OF_CLOTH_TAKEN") &&
!state.boltOfClothTakenShown) {
state.boltOfClothTakenShown = true;
- lineError = runtime.playDialogueLineWithVariant(0x46a, kFireman1Npc, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x46a, "FIREMAN1", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/fireman1_dialogue.h b/engines/harvester/npc/fireman1_dialogue.h
index e907af54a4a..2fb1648d4b4 100644
--- a/engines/harvester/npc/fireman1_dialogue.h
+++ b/engines/harvester/npc/fireman1_dialogue.h
@@ -34,7 +34,6 @@ public:
bool boltOfClothTakenShown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = Fireman1RoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.talkStatePending);
diff --git a/engines/harvester/npc/fireman2_dialogue.cpp b/engines/harvester/npc/fireman2_dialogue.cpp
index 302d18a2864..7616a26228c 100644
--- a/engines/harvester/npc/fireman2_dialogue.cpp
+++ b/engines/harvester/npc/fireman2_dialogue.cpp
@@ -26,10 +26,6 @@
namespace Harvester {
-bool Fireman2DialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("FIREMAN2");
-}
-
Common::Error Fireman2DialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
int wavId = 0x5c7;
diff --git a/engines/harvester/npc/fireman2_dialogue.h b/engines/harvester/npc/fireman2_dialogue.h
index 329ddddb895..d41fb329449 100644
--- a/engines/harvester/npc/fireman2_dialogue.h
+++ b/engines/harvester/npc/fireman2_dialogue.h
@@ -34,7 +34,6 @@ public:
int dialogueStateD2de4 = 0;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = Fireman2RoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.talkStateBlock);
diff --git a/engines/harvester/npc/gladiator_dialogue.cpp b/engines/harvester/npc/gladiator_dialogue.cpp
index 2a1b5926c4b..2a36fd292eb 100644
--- a/engines/harvester/npc/gladiator_dialogue.cpp
+++ b/engines/harvester/npc/gladiator_dialogue.cpp
@@ -28,7 +28,6 @@ namespace Harvester {
namespace {
-static const char *const kGladiatorNpc = "GLADIATOR";
static const char *const kGladiatorInterruptFlag = "GLADIATOR_INTERRUPT_CONVERSATION";
static const char *const kStartMercyTimerActionTag = "START_MERCY_TIMR";
static const char *const kDialogueC110FstPath = "GRAPHIC/FST/C110.FST";
@@ -37,29 +36,22 @@ static const int kGladiatorFollowupResponseLine = 0xc4;
} // End of namespace
-bool GladiatorDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kGladiatorNpc);
-}
-
Common::Error GladiatorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
- auto playGladiatorLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kGladiatorNpc, headVariant);
- };
auto queueGladiatorMonsterfyTransition = [&]() {
InteractionResult interaction;
- if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy(kGladiatorNpc)) {
+ if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy("GLADIATOR")) {
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
}
runtime.queueDialogueInteractionIfNeeded(interaction);
};
auto runGladiatorDeathBranch = [&](int leadWavId) -> Common::Error {
- Common::Error lineError = playGladiatorLine(leadWavId, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(leadWavId, "GLADIATOR", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playGladiatorLine(0x6cd, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x6cd, "GLADIATOR", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -72,11 +64,11 @@ Common::Error GladiatorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)runtime.startupScript().setRuntimeFlagValue(kGladiatorInterruptFlag, false);
- Common::Error lineError = playGladiatorLine(0x69c, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x69c, "GLADIATOR", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playGladiatorLine(0x6a3, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x6a3, "GLADIATOR", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -91,7 +83,7 @@ Common::Error GladiatorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex != 2)
return Common::kNoError;
- lineError = playGladiatorLine(0x6b3, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x6b3, "GLADIATOR", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -110,11 +102,11 @@ Common::Error GladiatorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex != 2)
return Common::kNoError;
- lineError = playGladiatorLine(0x6c7, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x6c7, "GLADIATOR", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playGladiatorLine(0x6cd, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x6cd, "GLADIATOR", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
diff --git a/engines/harvester/npc/gladiator_dialogue.h b/engines/harvester/npc/gladiator_dialogue.h
index bc6026d86eb..cb527c2e134 100644
--- a/engines/harvester/npc/gladiator_dialogue.h
+++ b/engines/harvester/npc/gladiator_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class GladiatorDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/hank_dialogue.cpp b/engines/harvester/npc/hank_dialogue.cpp
index eddf962cc83..8d1fd1393d1 100644
--- a/engines/harvester/npc/hank_dialogue.cpp
+++ b/engines/harvester/npc/hank_dialogue.cpp
@@ -178,10 +178,6 @@ static const DialogueLineEntry kHankResponse0EdTopicLines[] = {
} // End of namespace
-bool HankDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("HANK");
-}
-
Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
const bool europeanRelease = runtime.engine().isEuropeanRelease();
@@ -191,17 +187,8 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
int &hankTopicBufferLineIndex = state.currentTopicBufferLineIndex;
state.currentTopicBuffer.clear();
state.currentTopicBufferLineIndex = -1;
- auto assignHankTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(hankTopicBuffer, hankTopicBufferLineIndex,
- responseLineIndex, "Hank topic buffer");
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
- auto playLine = [&](int wavId, const char *speakerId = "HANK",
- int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, speakerId, headVariant);
- };
+ DialogueTopicBuffer topics(runtime, hankTopicBuffer, hankTopicBufferLineIndex, "Hank topic buffer");
+
auto hidePresentedInventoryItem = [&]() {
(void)runtime.startupScript().setRuntimeObjectVisible(
kInventoryOwnerName, usedItemName, false);
@@ -274,19 +261,19 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
lineError = runtime.playDialogueLine(0x70f, "HANK");
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xc8);
+ topics.assign(0xc8);
break;
case 2:
lineError = runtime.playDialogueLine(0x715, "HANK");
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xc9);
+ topics.assign(0xc9);
break;
case 3:
lineError = runtime.playDialogueLine(0x71c, "HANK");
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xca);
+ topics.assign(0xca);
break;
default:
break;
@@ -310,11 +297,9 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(
- kHankRangshotResponse1Lines, ARRAYSIZE(kHankRangshotResponse1Lines));
+ lineError = runtime.playDialogueEntrySequence(kHankRangshotResponse1Lines, ARRAYSIZE(kHankRangshotResponse1Lines));
} else if (responseIndex == 2) {
- lineError = playSequence(
- kHankRangshotResponse2Lines, ARRAYSIZE(kHankRangshotResponse2Lines));
+ lineError = runtime.playDialogueEntrySequence(kHankRangshotResponse2Lines, ARRAYSIZE(kHankRangshotResponse2Lines));
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -408,8 +393,8 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!skipHankFollowupBranches && runtime.startupScript().getFlagValue("BURNED_TV_STATION") &&
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
- Common::Error lineError = playSequence(
- kHankBurnedTvStationLines, ARRAYSIZE(kHankBurnedTvStationLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankBurnedTvStationLines,
+ ARRAYSIZE(kHankBurnedTvStationLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -519,8 +504,7 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
lineError = runtime.playDialogueLine(0xa20, "HANK");
break;
case 2:
- lineError = playSequence(
- kHankKarinFoundDeadResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kHankKarinFoundDeadResponse2Lines,
ARRAYSIZE(kHankKarinFoundDeadResponse2Lines));
break;
default:
@@ -563,35 +547,33 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, europeanRelease ? 0x30f : 0xd2)) {
- Common::Error lineError = playSequence(
- kHankMomTopicLines, ARRAYSIZE(kHankMomTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankMomTopicLines, ARRAYSIZE(kHankMomTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
runtime.setActiveSpeakerPortrait("HANK", 0);
- assignHankTopicBuffer(0xd5);
+ topics.assign(0xd5);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xd6)) {
- Common::Error lineError = playSequence(
- kHankSteveTopicLines, ARRAYSIZE(kHankSteveTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankSteveTopicLines, ARRAYSIZE(kHankSteveTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xd7);
+ topics.assign(0xd7);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xd8) ||
runtime.matchesResponseLine(selectedTopic, 0xd9)) {
- Common::Error lineError = playSequence(
- kHankLousyRatTopicLines, ARRAYSIZE(kHankLousyRatTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankLousyRatTopicLines,
+ ARRAYSIZE(kHankLousyRatTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xda);
+ topics.assign(0xda);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xdb) ||
runtime.matchesResponseLine(selectedTopic, 0xdc)) {
- Common::Error lineError = playSequence(
- kHankLightingOutTopicLines, ARRAYSIZE(kHankLightingOutTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankLightingOutTopicLines,
+ ARRAYSIZE(kHankLightingOutTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -600,67 +582,64 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playLine(0x79d);
+ lineError = runtime.playDialogueLineWithVariant(0x79d, "HANK", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xde);
+ topics.assign(0xde);
continue;
}
if (responseIndex == 2) {
- lineError = playLine(0x7a4);
+ lineError = runtime.playDialogueLineWithVariant(0x7a4, "HANK", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xdf);
+ topics.assign(0xdf);
continue;
}
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xe0)) {
- Common::Error lineError = playLine(0x7ad);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x7ad, "HANK", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xe1)) {
- Common::Error lineError = playSequence(
- kHankDaddyTopicLines, ARRAYSIZE(kHankDaddyTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankDaddyTopicLines, ARRAYSIZE(kHankDaddyTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xe2);
+ topics.assign(0xe2);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xe3)) {
- Common::Error lineError = playSequence(
- kHankGirlTopicLines, ARRAYSIZE(kHankGirlTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankGirlTopicLines, ARRAYSIZE(kHankGirlTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xe4);
+ topics.assign(0xe4);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xe5)) {
- Common::Error lineError = playLine(0x7f4);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x7f4, "HANK", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xe6)) {
- Common::Error lineError = playSequence(
- kHankTvTopicIntroLines, ARRAYSIZE(kHankTvTopicIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankTvTopicIntroLines,
+ ARRAYSIZE(kHankTvTopicIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC021FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(
- kHankTvTopicOutroLines, ARRAYSIZE(kHankTvTopicOutroLines));
+ lineError = runtime.playDialogueEntrySequence(kHankTvTopicOutroLines, ARRAYSIZE(kHankTvTopicOutroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xe8);
+ topics.assign(0xe8);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xe9)) {
- Common::Error lineError = playSequence(
- kHankCowboyShowTopicLines, ARRAYSIZE(kHankCowboyShowTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankCowboyShowTopicLines,
+ ARRAYSIZE(kHankCowboyShowTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -669,25 +648,24 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playLine(0x856);
+ lineError = runtime.playDialogueLineWithVariant(0x856, "HANK", 0);
} else if (responseIndex == 2) {
- lineError = playLine(0x85a);
+ lineError = runtime.playDialogueLineWithVariant(0x85a, "HANK", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xeb)) {
- Common::Error lineError = playSequence(
- kHankSickTopicLines, ARRAYSIZE(kHankSickTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankSickTopicLines, ARRAYSIZE(kHankSickTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHankTopicBuffer(0xec);
+ topics.assign(0xec);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xed)) {
- Common::Error lineError = playSequence(
- kHankResponse0EdTopicLines, ARRAYSIZE(kHankResponse0EdTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankResponse0EdTopicLines,
+ ARRAYSIZE(kHankResponse0EdTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
@@ -695,8 +673,7 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0xee) ||
runtime.matchesResponseLine(selectedTopic, 0xef) ||
runtime.matchesResponseLine(selectedTopic, 0xf0)) {
- Common::Error lineError = playSequence(
- kHankNewspaperFireSentinelTopicLines,
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankNewspaperFireSentinelTopicLines,
ARRAYSIZE(kHankNewspaperFireSentinelTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -704,16 +681,15 @@ Common::Error HankDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, 0xf1)) {
sharedState.discussedLodgeTopic = true;
- Common::Error lineError = playSequence(
- kHankLodgeTopicLines, ARRAYSIZE(kHankLodgeTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kHankLodgeTopicLines, ARRAYSIZE(kHankLodgeTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0xf2))
- return playLine(0x8dc);
+ return runtime.playDialogueLineWithVariant(0x8dc, "HANK", 0);
- Common::Error lineError = playLine(0xa32);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xa32, "HANK", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
diff --git a/engines/harvester/npc/hank_dialogue.h b/engines/harvester/npc/hank_dialogue.h
index b6e3a3028d0..fb21ef45799 100644
--- a/engines/harvester/npc/hank_dialogue.h
+++ b/engines/harvester/npc/hank_dialogue.h
@@ -44,7 +44,6 @@ public:
int currentTopicBufferLineIndex = -1;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = HankRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.pendingInitialConversation);
diff --git a/engines/harvester/npc/herrill_dialogue.cpp b/engines/harvester/npc/herrill_dialogue.cpp
index 5ff80e517ed..d5b32dece1c 100644
--- a/engines/harvester/npc/herrill_dialogue.cpp
+++ b/engines/harvester/npc/herrill_dialogue.cpp
@@ -30,9 +30,6 @@ namespace Harvester {
namespace {
-static const char *const kHerrillNpc = "HERRILL";
-static const char *const kHerrillLogNpc = "HERRILL_LOG";
-static const char *const kPcSpeaker = "PC";
static const char *const kGrandMuckNpc = "GRAND_MUCK";
static const int kGrandMuckDeathDamageType = 1;
@@ -40,26 +37,21 @@ static const int kHerrillGascanResponseLine = 0x280;
static const int kHerrillTopicBufferResponseLine = 0x281;
static const DialogueLineEntry kHerrillIntroLines[] = {
- { 0x2f59, kHerrillNpc, 1 },
- { 0x2f5e, kPcSpeaker, 0 },
- { 0x2f62, kHerrillNpc, 1 },
- { 0x1654, kPcSpeaker, 0 },
- { 0x2f6e, kHerrillNpc, 0 }
+ { 0x2f59, "HERRILL", 1 },
+ { 0x2f5e, "PC", 0 },
+ { 0x2f62, "HERRILL", 1 },
+ { 0x1654, "PC", 0 },
+ { 0x2f6e, "HERRILL", 0 }
};
static const DialogueLineEntry kHerrillGascanIntroLines[] = {
- { 0x30cf, kHerrillNpc, 1 },
- { 0x30d3, kPcSpeaker, 0 },
- { 0x30d8, kHerrillNpc, 0 }
+ { 0x30cf, "HERRILL", 1 },
+ { 0x30d3, "PC", 0 },
+ { 0x30d8, "HERRILL", 0 }
};
} // End of namespace
-bool HerrillDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kHerrillNpc) ||
- npcName.equalsIgnoreCase(kHerrillLogNpc);
-}
-
Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
HerrillRoomDialogueState &state = _state;
@@ -68,22 +60,8 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.currentTopicBuffer.clear();
state.currentTopicBufferLineIndex = -1;
- auto assignHerrillTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(herrillTopicBuffer, herrillTopicBufferLineIndex,
- responseLineIndex, "Herrill topic buffer");
- };
- auto playHerrillLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kHerrillNpc, headVariant);
- };
- auto playHerrillLogLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kHerrillLogNpc, headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kPcSpeaker, headVariant);
- };
- auto playGrandMuckLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kGrandMuckNpc, headVariant);
- };
+ DialogueTopicBuffer topics(runtime, herrillTopicBuffer, herrillTopicBufferLineIndex, "Herrill topic buffer");
+
auto queueLiveNpcDeathTransition = [&](const char *npcName) {
InteractionResult interaction;
if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy(
@@ -117,26 +95,26 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("HERRILL_IN_LODGE")) {
if (!runtime.startupScript().getFlagValue("PC_TALKED_TO_HERRILL")) {
- Common::Error lineError = playHerrillLogLine(0x31ca, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x31ca, "HERRILL_LOG", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x31ce, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x31ce, "PC", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playHerrillLogLine(0x31d2);
+ lineError = runtime.playDialogueLineWithVariant(0x31d2, "HERRILL_LOG", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x31da);
+ lineError = runtime.playDialogueLineWithVariant(0x31da, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playGrandMuckLine(0x31de, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x31de, kGrandMuckNpc, 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (shownWhaleyHerrillPhoto()) {
- lineError = playGrandMuckLine(0x31e0, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x31e0, kGrandMuckNpc, 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playHerrillLogLine(0x31e2, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x31e2, "HERRILL_LOG", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -155,7 +133,7 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
bool showGascanResponse = false;
if (!usedItemName.empty()) {
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
- return playHerrillLine(0x309f, 2);
+ return runtime.playDialogueLineWithVariant(0x309f, "HERRILL", 2);
}
const bool isCasketPhoto = usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY");
@@ -170,7 +148,7 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedLedgerEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownLedgersToAnyone, true);
}
- Common::Error lineError = playHerrillLine(0x30a6);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x30a6, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
int responseIndex = 0;
@@ -178,9 +156,9 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1)
- return playHerrillLine(0x30b1, 2);
+ return runtime.playDialogueLineWithVariant(0x30b1, "HERRILL", 2);
if (responseIndex == 2)
- return playHerrillLine(0x30b6, 2);
+ return runtime.playDialogueLineWithVariant(0x30b6, "HERRILL", 2);
return Common::kNoError;
}
if (usedItemName.equalsIgnoreCase("GASCAN")) {
@@ -190,9 +168,9 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceSheriffOwns, true);
sharedState.discussedTvDeedEvidence = 1;
const DialogueLineEntry lines[] = {
- { 0x3188, kHerrillNpc, 0 },
- { 0x318c, kPcSpeaker, 0 },
- { 0x3191, kHerrillNpc, 2 }
+ { 0x3188, "HERRILL", 0 },
+ { 0x318c, "PC", 0 },
+ { 0x3191, "HERRILL", 2 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
@@ -200,10 +178,10 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.dialogueStateD2eec = true;
if (!state.dialogueStateD2ce4)
return Common::kNoError;
- lineError = playHerrillLine(0x3198, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3198, "HERRILL", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playHerrillLine(0x319d, 2);
+ return runtime.playDialogueLineWithVariant(0x319d, "HERRILL", 2);
} else if (usedItemName.equalsIgnoreCase("NOTE") ||
usedItemName.equalsIgnoreCase("NOTE_PHOTOCOPY") ||
usedItemName.equalsIgnoreCase("CHECKBOOK") ||
@@ -211,16 +189,16 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
sharedState.discussedNoteCheckbookEvidence = 1;
const DialogueLineEntry lines[] = {
- { 0x30bf, kHerrillNpc, 0 },
- { 0x30c4, kPcSpeaker, 0 },
- { 0x30c8, kHerrillNpc, 0 }
+ { 0x30bf, "HERRILL", 0 },
+ { 0x30c4, "PC", 0 },
+ { 0x30c8, "HERRILL", 0 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
showGascanResponse = true;
} else {
- return playHerrillLine(0x3099);
+ return runtime.playDialogueLineWithVariant(0x3099, "HERRILL", 0);
}
}
@@ -234,7 +212,7 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.gascanPresented = false;
}
if (!sharedState.dialogueStateD2e98)
- return playPcLine(0x3123);
+ return runtime.playDialogueLineWithVariant(0x3123, "PC", 0);
state.dialogueStateD2ce4 = true;
int responseIndex = 0;
@@ -243,45 +221,45 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playHerrillLine(0x30e7);
+ lineError = runtime.playDialogueLineWithVariant(0x30e7, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2eb0) {
- lineError = playPcLine(0x30eb);
+ lineError = runtime.playDialogueLineWithVariant(0x30eb, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (sharedState.boyleGascanApplicationState) {
- lineError = playHerrillLine(0x30f4);
+ lineError = runtime.playDialogueLineWithVariant(0x30f4, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("HAVE_LODGE_APP")) {
- lineError = playPcLine(0x30fa);
+ lineError = runtime.playDialogueLineWithVariant(0x30fa, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playHerrillLine(0x30ff, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x30ff, "HERRILL", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2eec) {
- lineError = playHerrillLine(0x3104);
+ lineError = runtime.playDialogueLineWithVariant(0x3104, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- return playHerrillLine(0x3109, 2);
+ return runtime.playDialogueLineWithVariant(0x3109, "HERRILL", 2);
}
- lineError = playHerrillLine(0x30f0);
+ lineError = runtime.playDialogueLineWithVariant(0x30f0, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x3110);
+ lineError = runtime.playDialogueLineWithVariant(0x3110, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playHerrillLine(0x3114, 3);
+ return runtime.playDialogueLineWithVariant(0x3114, "HERRILL", 3);
}
if (responseIndex == 2)
- return playHerrillLine(0x311b, 1);
+ return runtime.playDialogueLineWithVariant(0x311b, "HERRILL", 1);
return Common::kNoError;
}
@@ -292,9 +270,9 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
kHerrillIntroLines, ARRAYSIZE(kHerrillIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(kHerrillTopicBufferResponseLine);
+ topics.assign(kHerrillTopicBufferResponseLine);
} else {
- Common::Error lineError = playHerrillLine(0x2ffb);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2ffb, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -302,34 +280,34 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephMidgamePlayedShown) {
state.stephMidgamePlayedShown = true;
- Common::Error lineError = playHerrillLine(0x3004, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3004, "HERRILL", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getCurrentStoryDayIndex() == 5 &&
!state.dayFiveShown) {
state.dayFiveShown = true;
- Common::Error lineError = playHerrillLine(0x300d, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x300d, "HERRILL", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("SCRATCHED_TUCKER") &&
!state.scratchedTuckerShown) {
state.scratchedTuckerShown = true;
- Common::Error lineError = playHerrillLine(0x3019, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3019, "HERRILL", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playHerrillLine(0x3022, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x3022, "HERRILL", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("BARBER_POLE_STOLEN") &&
!state.barberPoleStolenShown) {
state.barberPoleStolenShown = true;
- Common::Error lineError = playHerrillLine(0x3029);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3029, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playHerrillLine(0x302f, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x302f, "HERRILL", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -337,50 +315,52 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.karinKidnapedShown) {
state.karinKidnapedShown = true;
sharedState.karinKidnapedDialogueState = true;
- Common::Error lineError = playHerrillLine(0x3041);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3041, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("KARIN_FOUND_ALIVE") &&
!state.karinFoundAliveShown) {
state.karinFoundAliveShown = true;
- Common::Error lineError = playHerrillLine(0x304c, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x304c, "HERRILL", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = shownWhaleyHerrillPhoto() ? playHerrillLine(0x3050, 2) : playHerrillLine(0x3057, 1);
+ lineError = shownWhaleyHerrillPhoto()
+ ? runtime.playDialogueLineWithVariant(0x3050, "HERRILL", 2)
+ : runtime.playDialogueLineWithVariant(0x3057, "HERRILL", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("KARIN_FOUND_DEAD") &&
!state.karinFoundDeadShown) {
state.karinFoundDeadShown = true;
- Common::Error lineError = playHerrillLine(0x305e);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x305e, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x461b, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x461b, "PC", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED")) {
- lineError = playHerrillLine(0x3067, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3067, "HERRILL", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
lineError = shownWhaleyHerrillPhoto()
- ? playHerrillLine(0x306b, 2)
- : playHerrillLine(0x3073, 3);
+ ? runtime.playDialogueLineWithVariant(0x306b, "HERRILL", 2)
+ : runtime.playDialogueLineWithVariant(0x3073, "HERRILL", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("DINER_BURNED") &&
!state.dinerBurnedShown) {
state.dinerBurnedShown = true;
- Common::Error lineError = playHerrillLine(0x307d, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x307d, "HERRILL", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (shownWhaleyHerrillPhoto() && !state.whaleyHerrillFollowupShown) {
state.whaleyHerrillFollowupShown = true;
- Common::Error lineError = playHerrillLine(0x31a6, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x31a6, "HERRILL", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
int responseIndex = 0;
@@ -388,14 +368,14 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playHerrillLine(0x31b1, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x31b1, "HERRILL", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
state.dialogueSuppressed = true;
return Common::kNoError;
}
if (responseIndex == 2) {
- lineError = playHerrillLine(0x31b9, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x31b9, "HERRILL", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
state.requiresEvidenceForDialogue = true;
@@ -412,89 +392,89 @@ Common::Error HerrillDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (selectedTopic.empty())
return Common::kNoError;
if (runtime.matchesResponseLine(selectedTopic, 0x283)) {
- return playHerrillLine(0x2ff4);
+ return runtime.playDialogueLineWithVariant(0x2ff4, "HERRILL", 0);
}
if (runtime.matchesResponseLine(selectedTopic, 0x284)) {
const DialogueLineEntry lines[] = {
- { 0x2f7b, kPcSpeaker, 2 },
- { 0x2f7f, kHerrillNpc, 0 },
- { 0x2f80, kHerrillNpc, 0 },
- { 0x2f81, kHerrillNpc, 0 }
+ { 0x2f7b, "PC", 2 },
+ { 0x2f7f, "HERRILL", 0 },
+ { 0x2f80, "HERRILL", 0 },
+ { 0x2f81, "HERRILL", 0 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x285);
+ topics.assign(0x285);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x286)) {
const DialogueLineEntry lines[] = {
- { 0x2f8f, kHerrillNpc, 0 },
- { 0x2f90, kHerrillNpc, 0 },
- { 0x2f91, kHerrillNpc, 1 }
+ { 0x2f8f, "HERRILL", 0 },
+ { 0x2f90, "HERRILL", 0 },
+ { 0x2f91, "HERRILL", 1 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x287);
+ topics.assign(0x287);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x288)) {
const DialogueLineEntry lines[] = {
- { 0x2f9e, kHerrillNpc, 1 },
- { 0x2fa3, kPcSpeaker, 2 },
- { 0x2fa7, kHerrillNpc, 1 }
+ { 0x2f9e, "HERRILL", 1 },
+ { 0x2fa3, "PC", 2 },
+ { 0x2fa7, "HERRILL", 1 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x289);
+ topics.assign(0x289);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x28a)) {
const DialogueLineEntry lines[] = {
- { 0x2fb2, kPcSpeaker, 0 },
- { 0x2fb6, kHerrillNpc, 0 },
- { 0x2fbe, kHerrillNpc, 1 },
- { 0x2fc2, kHerrillNpc, 1 }
+ { 0x2fb2, "PC", 0 },
+ { 0x2fb6, "HERRILL", 0 },
+ { 0x2fbe, "HERRILL", 1 },
+ { 0x2fc2, "HERRILL", 1 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x28b);
+ topics.assign(0x28b);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x28c)) {
const DialogueLineEntry lines[] = {
- { 0x2fcd, kPcSpeaker, 0 },
- { 0x2fd2, kHerrillNpc, 0 }
+ { 0x2fcd, "PC", 0 },
+ { 0x2fd2, "HERRILL", 0 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x28d);
+ topics.assign(0x28d);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x28e) ||
runtime.matchesResponseLine(selectedTopic, 0x28f)) {
sharedState.discussedLodgeTopic = true;
- Common::Error lineError = playHerrillLine(0x2fdd);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2fdd, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x290);
+ topics.assign(0x290);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x291)) {
- Common::Error lineError = playHerrillLine(0x2fe9, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2fe9, "HERRILL", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignHerrillTopicBuffer(0x292);
+ topics.assign(0x292);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x293))
- return playHerrillLine(0x2ff4);
+ return runtime.playDialogueLineWithVariant(0x2ff4, "HERRILL", 0);
- Common::Error lineError = playHerrillLine(0x3099);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3099, "HERRILL", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/herrill_dialogue.h b/engines/harvester/npc/herrill_dialogue.h
index 0a68d9356de..5f174dcf1f6 100644
--- a/engines/harvester/npc/herrill_dialogue.h
+++ b/engines/harvester/npc/herrill_dialogue.h
@@ -47,7 +47,6 @@ public:
int currentTopicBufferLineIndex = -1;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = HerrillRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/inquisitor_dialogue.cpp b/engines/harvester/npc/inquisitor_dialogue.cpp
index 7e7e50a739a..f4ebd223706 100644
--- a/engines/harvester/npc/inquisitor_dialogue.cpp
+++ b/engines/harvester/npc/inquisitor_dialogue.cpp
@@ -28,17 +28,12 @@ namespace Harvester {
namespace {
-static const char *const kInquisitorNpc = "INQUISITOR";
static const char *const kPainSolvedFlag = "PAIN_SOLVED";
static const char *const kStartInquisitorTimerActionTag = "START_INQ_TIM";
static const char *const kTorch2FstPath = "GRAPHIC/FST/TORCH2.FST";
} // End of namespace
-bool InquisitorDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kInquisitorNpc);
-}
-
Common::Error InquisitorDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
if (runtime.startupScript().getFlagValue(kPainSolvedFlag) || !_state.talkStatePending)
@@ -46,19 +41,15 @@ Common::Error InquisitorDialogueHandler::handleDialogue(DialogueRuntime &runtime
_state.talkStatePending = false;
- auto playInquisitorLine = [&](int wavId) -> Common::Error {
- return runtime.playDialogueLine(wavId, kInquisitorNpc);
- };
-
- Common::Error lineError = playInquisitorLine(0x18e7);
+ Common::Error lineError = runtime.playDialogueLine(0x18e7, "INQUISITOR");
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playInquisitorLine(0x18e8);
+ lineError = runtime.playDialogueLine(0x18e8, "INQUISITOR");
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playInquisitorLine(0x18e9);
+ lineError = runtime.playDialogueLine(0x18e9, "INQUISITOR");
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -66,7 +57,7 @@ Common::Error InquisitorDialogueHandler::handleDialogue(DialogueRuntime &runtime
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playInquisitorLine(0x18f8);
+ lineError = runtime.playDialogueLine(0x18f8, "INQUISITOR");
if (lineError.getCode() != Common::kNoError)
return lineError;
diff --git a/engines/harvester/npc/inquisitor_dialogue.h b/engines/harvester/npc/inquisitor_dialogue.h
index dd91094d0e5..1f3d1298fa3 100644
--- a/engines/harvester/npc/inquisitor_dialogue.h
+++ b/engines/harvester/npc/inquisitor_dialogue.h
@@ -32,7 +32,6 @@ public:
bool talkStatePending = true;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = InquisitorRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.talkStatePending);
diff --git a/engines/harvester/npc/jimmy_dialogue.cpp b/engines/harvester/npc/jimmy_dialogue.cpp
index a1bde6cfb31..37f74137387 100644
--- a/engines/harvester/npc/jimmy_dialogue.cpp
+++ b/engines/harvester/npc/jimmy_dialogue.cpp
@@ -29,8 +29,6 @@ namespace Harvester {
namespace {
-static const char *const kJimmyNpc = "JIMMY";
-static const char *const kPcSpeaker = "PC";
static const char *const kRahRoomName = "RAH";
static const char *const kJimmyFirstMeetingFlag = "PAPER_CHK_1";
static const char *const kGivenPaperTodayFlag = "GIVEN_PAPER_TODAY";
@@ -40,74 +38,57 @@ static const int kJimmyThirdResponseLineIndex = 0xf7;
static const int kJimmySneakersResponseLineIndex = 0xf8;
static const DialogueLineEntry kJimmyPaperHandoffLines[] = {
- { 0x4a4c, kJimmyNpc, 1 },
- { 0x4a52, kPcSpeaker, 0 }
+ { 0x4a4c, "JIMMY", 1 },
+ { 0x4a52, "PC", 0 }
};
static const DialogueLineEntry kJimmyFirstMeetingFollowupLines[] = {
- { 0x4a6b, kJimmyNpc, 0 },
- { 0x4a70, kPcSpeaker, 0 },
- { 0x4a74, kJimmyNpc, 0 },
- { 0x4a7a, kJimmyNpc, 0 }
+ { 0x4a6b, "JIMMY", 0 },
+ { 0x4a70, "PC", 0 },
+ { 0x4a74, "JIMMY", 0 },
+ { 0x4a7a, "JIMMY", 0 }
};
static const DialogueLineEntry kJimmySecondResponsePreludeLines[] = {
- { 0x4a8a, kPcSpeaker, 0 },
- { 0x4a8e, kJimmyNpc, 1 }
+ { 0x4a8a, "PC", 0 },
+ { 0x4a8e, "JIMMY", 1 }
};
static const DialogueLineEntry kJimmyNoSneakersLines[] = {
- { 0x4aa6, kJimmyNpc, 0 },
- { 0x4aaa, kPcSpeaker, 0 },
- { 0x4aae, kJimmyNpc, 2 }
+ { 0x4aa6, "JIMMY", 0 },
+ { 0x4aaa, "PC", 0 },
+ { 0x4aae, "JIMMY", 2 }
};
static const DialogueLineEntry kJimmyLedgersAndCorpseEvidenceLines[] = {
- { 0x4b00, kJimmyNpc, 0 },
- { 0x4b04, kPcSpeaker, 0 },
- { 0x4b08, kJimmyNpc, 0 },
- { 0x4b0c, kPcSpeaker, 0 },
- { 0x4b10, kJimmyNpc, 0 },
- { 0x4b15, kPcSpeaker, 0 },
- { 0x4b19, kJimmyNpc, 0 }
+ { 0x4b00, "JIMMY", 0 },
+ { 0x4b04, "PC", 0 },
+ { 0x4b08, "JIMMY", 0 },
+ { 0x4b0c, "PC", 0 },
+ { 0x4b10, "JIMMY", 0 },
+ { 0x4b15, "PC", 0 },
+ { 0x4b19, "JIMMY", 0 }
};
static const DialogueLineEntry kJimmyBlackmailEvidenceLines[] = {
- { 0x4b21, kJimmyNpc, 0 },
- { 0x4b25, kPcSpeaker, 0 },
- { 0x4b29, kJimmyNpc, 0 },
- { 0x4b2d, kPcSpeaker, 0 },
- { 0x4b31, kJimmyNpc, 1 }
+ { 0x4b21, "JIMMY", 0 },
+ { 0x4b25, "PC", 0 },
+ { 0x4b29, "JIMMY", 0 },
+ { 0x4b2d, "PC", 0 },
+ { 0x4b31, "JIMMY", 1 }
};
} // End of namespace
-bool JimmyDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("JIMMY");
-}
-
Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
JimmyRoomDialogueState &state = _state;
Common::Error lineError = Common::kNoError;
- auto playJimmyLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kJimmyNpc, headVariant);
- };
- auto playJimmySequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
auto hasInventoryItem = [&](const char *objectName) {
return runtime.startupScript().isObjectInInventory(objectName);
};
- auto executeActionTagIfSet = [&](const char *tag) {
- InteractionResult interaction;
- if (!runtime.executeActionTag(tag, interaction))
- return;
- runtime.applyImmediateDialogueInteractionEffects(interaction);
- runtime.queueDialogueInteractionIfNeeded(interaction);
- };
auto restoreItemToRah = [&](const char *objectName) {
(void)runtime.startupScript().resetRuntimeObjectToInitialState(objectName);
(void)runtime.startupScript().setRuntimeObjectVisible(kRahRoomName, objectName, true);
@@ -120,8 +101,8 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (state.paperHandoffStateSet)
return Common::kNoError;
- Common::Error preludeError = playJimmySequence(
- kJimmyPaperHandoffLines, ARRAYSIZE(kJimmyPaperHandoffLines));
+ Common::Error preludeError = runtime.playDialogueEntrySequence(kJimmyPaperHandoffLines,
+ ARRAYSIZE(kJimmyPaperHandoffLines));
if (preludeError.getCode() != Common::kNoError)
return preludeError;
@@ -136,7 +117,7 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex == 1) {
if (hasInventoryItem("SNEAKERS")) {
- Common::Error lineError = playJimmyLine(0x4a9e, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x4a9e, "JIMMY", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -144,10 +125,10 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
}
- return playJimmySequence(kJimmyNoSneakersLines, ARRAYSIZE(kJimmyNoSneakersLines));
+ return runtime.playDialogueEntrySequence(kJimmyNoSneakersLines, ARRAYSIZE(kJimmyNoSneakersLines));
}
if (responseIndex == 2)
- return playJimmyLine(0x4ab4, 1);
+ return runtime.playDialogueLineWithVariant(0x4ab4, "JIMMY", 1);
return Common::kNoError;
};
@@ -158,11 +139,11 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- Common::Error lineError = playJimmyLine(0x4a86, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x4a86, "JIMMY", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playJimmySequence(kJimmySecondResponsePreludeLines,
+ lineError = runtime.playDialogueEntrySequence(kJimmySecondResponsePreludeLines,
ARRAYSIZE(kJimmySecondResponsePreludeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -170,13 +151,13 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return runSneakersOfferMenu();
}
if (responseIndex == 2)
- return playJimmyLine(0x4abc, 0);
+ return runtime.playDialogueLineWithVariant(0x4abc, "JIMMY", 0);
return Common::kNoError;
};
auto playJimmyNoItemFallback = [&]() -> Common::Error {
if (hasInventoryItem("SNEAKERS") && !hasInventoryItem("BROOMKEY")) {
- Common::Error sneakersLineError = playJimmyLine(0x4ac3, 0);
+ Common::Error sneakersLineError = runtime.playDialogueLineWithVariant(0x4ac3, "JIMMY", 0);
if (sneakersLineError.getCode() != Common::kNoError)
return sneakersLineError;
@@ -185,29 +166,28 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return sneakersPromptError;
}
if (runtime.startupScript().getFlagValue("PAPER_CHK_4"))
- return playJimmyLine(0x4ae2, 2);
+ return runtime.playDialogueLineWithVariant(0x4ae2, "JIMMY", 2);
if (runtime.startupScript().getFlagValue("PAPER_CHK_3"))
- return playJimmyLine(0x4adb, 2);
+ return runtime.playDialogueLineWithVariant(0x4adb, "JIMMY", 2);
if (runtime.startupScript().getFlagValue("PAPER_CHK_2"))
- return playJimmyLine(0x4ad4, 2);
+ return runtime.playDialogueLineWithVariant(0x4ad4, "JIMMY", 2);
- return playJimmyLine(0x4b38, 0);
+ return runtime.playDialogueLineWithVariant(0x4b38, "JIMMY", 0);
};
if (!usedItemName.empty()) {
if (usedItemName.equalsIgnoreCase("NEWSPAPER")) {
(void)runtime.startupScript().setRuntimeFlagValue(kGivenPaperTodayFlag, true);
restoreItemToRah("NEWSPAPER");
- executeActionTagIfSet("ACTV_HOUSE_EXIT");
+ runtime.executeAndQueueAction("ACTV_HOUSE_EXIT");
lineError = playPaperHandoffPreludeIfNeeded();
if (lineError.getCode() != Common::kNoError)
return lineError;
const bool playJimmyRevisitBark = runtime.getRandomNumber(1) == 0;
- lineError = playJimmyLine(
- playJimmyRevisitBark ? 0x4acc : 0x4a4b,
- playJimmyRevisitBark ? 0 : 1);
+ lineError = runtime.playDialogueLineWithVariant(playJimmyRevisitBark ? 0x4acc : 0x4a4b,
+ "JIMMY", playJimmyRevisitBark ? 0 : 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -218,7 +198,7 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
- return playJimmyLine(0x4af8, 1);
+ return runtime.playDialogueLineWithVariant(0x4af8, "JIMMY", 1);
}
if (((usedItemName.equalsIgnoreCase("LEDGER") ||
usedItemName.equalsIgnoreCase("LEDGER2")) &&
@@ -231,7 +211,7 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
} else {
sharedState.discussedLedgerEvidence = 1;
}
- return playJimmySequence(kJimmyLedgersAndCorpseEvidenceLines,
+ return runtime.playDialogueEntrySequence(kJimmyLedgersAndCorpseEvidenceLines,
ARRAYSIZE(kJimmyLedgersAndCorpseEvidenceLines));
}
if (usedItemName.equalsIgnoreCase("NOTE") ||
@@ -239,11 +219,10 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CHECKBOOK") ||
usedItemName.equalsIgnoreCase("CHECKBOOK_PHOTOCOPY")) {
sharedState.discussedNoteCheckbookEvidence = 1;
- return playJimmySequence(kJimmyBlackmailEvidenceLines,
- ARRAYSIZE(kJimmyBlackmailEvidenceLines));
+ return runtime.playDialogueEntrySequence(kJimmyBlackmailEvidenceLines, ARRAYSIZE(kJimmyBlackmailEvidenceLines));
}
if (usedItemName.equalsIgnoreCase("SNEAKERS")) {
- lineError = playJimmyLine(0x4a9e, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x4a9e, "JIMMY", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -251,7 +230,7 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
}
- return playJimmyLine(0x4af2, 0);
+ return runtime.playDialogueLineWithVariant(0x4af2, "JIMMY", 0);
}
if (state.firstNoItemLinePending) {
@@ -260,7 +239,7 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playJimmyLine(0x4a58, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x4a58, "JIMMY", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -273,16 +252,17 @@ Common::Error JimmyDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playJimmyLine(0x4a63, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x4a63, "JIMMY", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playJimmyLine(0x4a67, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x4a67, "JIMMY", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playJimmySequence(kJimmyFirstMeetingFollowupLines, ARRAYSIZE(kJimmyFirstMeetingFollowupLines));
+ lineError = runtime.playDialogueEntrySequence(kJimmyFirstMeetingFollowupLines,
+ ARRAYSIZE(kJimmyFirstMeetingFollowupLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
diff --git a/engines/harvester/npc/jimmy_dialogue.h b/engines/harvester/npc/jimmy_dialogue.h
index 47e723b79e7..5d563ff962a 100644
--- a/engines/harvester/npc/jimmy_dialogue.h
+++ b/engines/harvester/npc/jimmy_dialogue.h
@@ -33,7 +33,6 @@ public:
bool paperHandoffStateSet = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = JimmyRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.firstNoItemLinePending);
diff --git a/engines/harvester/npc/johnson_dialogue.cpp b/engines/harvester/npc/johnson_dialogue.cpp
index e9d35d8fed2..d49ed9ae3d6 100644
--- a/engines/harvester/npc/johnson_dialogue.cpp
+++ b/engines/harvester/npc/johnson_dialogue.cpp
@@ -29,8 +29,6 @@ namespace Harvester {
namespace {
-static const char *const kJohnsonNpc = "JOHNSON";
-static const char *const kPcSpeaker = "PC";
static const int kJohnsonInitialTopicBufferLine = 0x176;
static const int kJohnsonResponseTopicBufferLine = 0x17b;
@@ -43,59 +41,55 @@ static const int kJohnsonGenericReplyTopicLines[] = { 0x180, 0x181, 0x182 };
static const int kJohnsonSecondGenericReplyTopicLines[] = { 0x184, 0x185 };
static const DialogueLineEntry kJohnsonIntroLines[] = {
- { 0xa86, kJohnsonNpc, 1 },
- { 0xa8a, kPcSpeaker, 0 },
- { 0xa8e, kJohnsonNpc, 1 },
- { 0xa97, kPcSpeaker, 0 },
- { 0xa9b, kJohnsonNpc, 0 }
+ { 0xa86, "JOHNSON", 1 },
+ { 0xa8a, "PC", 0 },
+ { 0xa8e, "JOHNSON", 1 },
+ { 0xa97, "PC", 0 },
+ { 0xa9b, "JOHNSON", 0 }
};
static const DialogueLineEntry kJohnsonWhaleyPhotoLines[] = {
- { 0xb75, kJohnsonNpc, 1 },
- { 0xb7b, kPcSpeaker, 1 },
- { 0xb80, kJohnsonNpc, 1 }
+ { 0xb75, "JOHNSON", 1 },
+ { 0xb7b, "PC", 1 },
+ { 0xb80, "JOHNSON", 1 }
};
static const DialogueLineEntry kJohnsonLedgerLines[] = {
- { 0xba0, kJohnsonNpc, 1 },
- { 0xba4, kPcSpeaker, 0 },
- { 0xba8, kJohnsonNpc, 1 }
+ { 0xba0, "JOHNSON", 1 },
+ { 0xba4, "PC", 0 },
+ { 0xba8, "JOHNSON", 1 }
};
static const DialogueLineEntry kJohnsonScratchedTuckerLines[] = {
- { 0xc25, kJohnsonNpc, 2 },
- { 0xc2b, kJohnsonNpc, 3 },
- { 0xc30, kJohnsonNpc, 2 }
+ { 0xc25, "JOHNSON", 2 },
+ { 0xc2b, "JOHNSON", 3 },
+ { 0xc30, "JOHNSON", 2 }
};
static const DialogueLineEntry kJohnsonBoltOfClothLines[] = {
- { 0xc5f, kJohnsonNpc, 3 },
- { 0xc69, kJohnsonNpc, 3 }
+ { 0xc5f, "JOHNSON", 3 },
+ { 0xc69, "JOHNSON", 3 }
};
static const DialogueLineEntry kJohnsonStephMidgameLines[] = {
- { 0xbf0, kJohnsonNpc, 3 },
- { 0xbf1, kJohnsonNpc, 3 },
- { 0xbf2, kJohnsonNpc, 3 }
+ { 0xbf0, "JOHNSON", 3 },
+ { 0xbf1, "JOHNSON", 3 },
+ { 0xbf2, "JOHNSON", 3 }
};
static const DialogueLineEntry kJohnsonKarinKidnapedLines[] = {
- { 0xbff, kJohnsonNpc, 0 },
- { 0xc06, kJohnsonNpc, 0 }
+ { 0xbff, "JOHNSON", 0 },
+ { 0xc06, "JOHNSON", 0 }
};
static const DialogueLineEntry kJohnsonBarberPoleStolenLines[] = {
- { 0xc46, kJohnsonNpc, 3 },
- { 0xc4d, kJohnsonNpc, 3 },
- { 0xc59, kJohnsonNpc, 3 }
+ { 0xc46, "JOHNSON", 3 },
+ { 0xc4d, "JOHNSON", 3 },
+ { 0xc59, "JOHNSON", 3 }
};
} // End of namespace
-bool JohnsonDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("JOHNSON");
-}
-
Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
JohnsonRoomDialogueState &state = _state;
@@ -104,24 +98,18 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.currentTopicBuffer.clear();
state.currentTopicBufferLineIndex = -1;
- auto assignJohnsonTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(johnsonTopicBuffer, johnsonTopicBufferLineIndex,
- responseLineIndex, "Johnson topic buffer");
- };
- auto playJohnsonLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kJohnsonNpc, headVariant);
- };
+ DialogueTopicBuffer topics(runtime, johnsonTopicBuffer, johnsonTopicBufferLineIndex, "Johnson topic buffer");
if (runtime.startupScript().getFlagValue("2ND_SCRATCH_TUCKER"))
- return playJohnsonLine(0xbe6, 2);
+ return runtime.playDialogueLineWithVariant(0xbe6, "JOHNSON", 2);
if (runtime.startupScript().getFlagValue("TRY_TO_SCRATCH_TUCKER") &&
!state.tryToScratchTuckerShown) {
state.tryToScratchTuckerShown = true;
- return playJohnsonLine(0xbe0, 2);
+ return runtime.playDialogueLineWithVariant(0xbe0, "JOHNSON", 2);
}
if (runtime.startupScript().getFlagValue("OPENING_MANHOLE_DAYTIME"))
{
- Common::Error lineError = playJohnsonLine(0xbe0, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xbe0, "JOHNSON", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -140,16 +128,16 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
sharedState.discussedCasketPhotoEvidence = 1;
- Common::Error lineError = playJohnsonLine(0xb89, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xb89, "JOHNSON", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!sharedState.dialogueStateD2ebc)
return Common::kNoError;
const DialogueLineEntry followupLines[] = {
- { 0xb90, kPcSpeaker, 0 },
- { 0xb94, kJohnsonNpc, 0 },
- { 0xb99, kJohnsonNpc, 0 }
+ { 0xb90, "PC", 0 },
+ { 0xb94, "JOHNSON", 0 },
+ { 0xb99, "JOHNSON", 0 }
};
return runtime.playDialogueEntrySequence(followupLines, ARRAYSIZE(followupLines));
}
@@ -167,16 +155,16 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CHECKBOOK_PHOTOCOPY")) {
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
sharedState.discussedNoteCheckbookEvidence = 1;
- return playJohnsonLine(0xbb1, 1);
+ return runtime.playDialogueLineWithVariant(0xbb1, "JOHNSON", 1);
}
if (usedItemName.equalsIgnoreCase("TV_DEED") ||
usedItemName.equalsIgnoreCase("TV_DEED_PHOTOCOPY")) {
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceSheriffOwns, true);
sharedState.discussedTvDeedEvidence = 1;
- return playJohnsonLine(0xbce, 1);
+ return runtime.playDialogueLineWithVariant(0xbce, "JOHNSON", 1);
}
- return playJohnsonLine(0xb6f);
+ return runtime.playDialogueLineWithVariant(0xb6f, "JOHNSON", 0);
}
if (runtime.startupScript().getFlagValue("SCRATCHED_TUCKER") &&
@@ -204,9 +192,9 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
- assignJohnsonTopicBuffer(kJohnsonInitialTopicBufferLine);
+ topics.assign(kJohnsonInitialTopicBufferLine);
} else {
- Common::Error lineError = playJohnsonLine(0xb62);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xb62, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -232,10 +220,10 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("KARIN_FOUND_ALIVE") &&
!state.karinFoundAliveShown) {
state.karinFoundAliveShown = true;
- Common::Error lineError = playJohnsonLine(0xc13, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xc13, "JOHNSON", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playJohnsonLine(0xc17);
+ lineError = runtime.playDialogueLineWithVariant(0xc17, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -250,28 +238,28 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("DINER_BURNED") &&
!state.dinerBurnedShown) {
state.dinerBurnedShown = true;
- Common::Error lineError = playJohnsonLine(0xc6f, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xc6f, "JOHNSON", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("PC_ESCAPED_JAIL") &&
!state.escapedJailShown) {
state.escapedJailShown = true;
- Common::Error lineError = playJohnsonLine(0xc77, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xc77, "JOHNSON", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("GOT_REMAINS_FOR_LODGE") &&
!state.gotRemainsForLodgeShown) {
state.gotRemainsForLodgeShown = true;
- Common::Error lineError = playJohnsonLine(0xc7f);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xc7f, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("BURNED_TV_STATION") &&
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
- Common::Error lineError = playJohnsonLine(0xc8f);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xc8f, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -286,11 +274,11 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
if (runtime.matchesAnyResponseLine(selectedTopic, kJohnsonDirectExitTopicLines,
ARRAYSIZE(kJohnsonDirectExitTopicLines))) {
- return playJohnsonLine(0xbda, 1);
+ return runtime.playDialogueLineWithVariant(0xbda, "JOHNSON", 1);
}
if (runtime.matchesAnyResponseLine(selectedTopic, kJohnsonIntroductionTopicLines,
ARRAYSIZE(kJohnsonIntroductionTopicLines))) {
- Common::Error lineError = playJohnsonLine(0xaa6);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xaa6, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -301,79 +289,79 @@ Common::Error JohnsonDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playJohnsonLine(0xab4, 2);
+ lineError = runtime.playDialogueLineWithVariant(0xab4, "JOHNSON", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playJohnsonLine(0xab9);
+ lineError = runtime.playDialogueLineWithVariant(0xab9, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
const DialogueLineEntry followupLines[] = {
- { 0xabd, kJohnsonNpc, 0 },
- { 0xac3, kPcSpeaker, 0 },
- { 0xac7, kJohnsonNpc, 2 }
+ { 0xabd, "JOHNSON", 0 },
+ { 0xac3, "PC", 0 },
+ { 0xac7, "JOHNSON", 2 }
};
lineError = runtime.playDialogueEntrySequence(followupLines, ARRAYSIZE(followupLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignJohnsonTopicBuffer(kJohnsonResponseTopicBufferLine);
+ topics.assign(kJohnsonResponseTopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x17c)) {
const DialogueLineEntry lines[] = {
- { 0xb17, kJohnsonNpc, 0 },
- { 0xb1c, kPcSpeaker, 0 },
- { 0xb20, kJohnsonNpc, 1 }
+ { 0xb17, "JOHNSON", 0 },
+ { 0xb1c, "PC", 0 },
+ { 0xb20, "JOHNSON", 1 }
};
Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignJohnsonTopicBuffer(kJohnsonStephTopicBufferLine);
+ topics.assign(kJohnsonStephTopicBufferLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x17e)) {
- Common::Error lineError = playJohnsonLine(0xb2d, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xb2d, "JOHNSON", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignJohnsonTopicBuffer(kJohnsonKarinAliveTopicBufferLine);
+ topics.assign(kJohnsonKarinAliveTopicBufferLine);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kJohnsonGenericReplyTopicLines,
ARRAYSIZE(kJohnsonGenericReplyTopicLines))) {
- Common::Error lineError = playJohnsonLine(0xb3a);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xb3a, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignJohnsonTopicBuffer(0x183);
+ topics.assign(0x183);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kJohnsonSecondGenericReplyTopicLines,
ARRAYSIZE(kJohnsonSecondGenericReplyTopicLines))) {
- Common::Error lineError = playJohnsonLine(0xb46);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xb46, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignJohnsonTopicBuffer(0x186);
+ topics.assign(0x186);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x187)) {
Common::Error lineError = runtime.playDialogueLineWithVariant(0xb52, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playJohnsonLine(0xb56, 2);
+ lineError = runtime.playDialogueLineWithVariant(0xb56, "JOHNSON", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignJohnsonTopicBuffer(0x188);
+ topics.assign(0x188);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x189))
continue;
- Common::Error lineError = playJohnsonLine(0xb69);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0xb69, "JOHNSON", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playJohnsonLine(0xbda, 1);
+ return runtime.playDialogueLineWithVariant(0xbda, "JOHNSON", 1);
}
}
diff --git a/engines/harvester/npc/johnson_dialogue.h b/engines/harvester/npc/johnson_dialogue.h
index 53ceed08417..75d9eee8024 100644
--- a/engines/harvester/npc/johnson_dialogue.h
+++ b/engines/harvester/npc/johnson_dialogue.h
@@ -45,7 +45,6 @@ public:
int currentTopicBufferLineIndex = -1;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = JohnsonRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/karin_dialogue.cpp b/engines/harvester/npc/karin_dialogue.cpp
index d9d2fae9bf6..a6e2eb74a4d 100644
--- a/engines/harvester/npc/karin_dialogue.cpp
+++ b/engines/harvester/npc/karin_dialogue.cpp
@@ -28,87 +28,60 @@ namespace Harvester {
namespace {
-static const char *const kKarinNpc = "KARIN";
-static const char *const kKarinStandingNpc = "KARIN_STANDING";
-static const char *const kKarinCem10Npc = "KARIN_CEM10";
-static const char *const kKarinOfficeNpc = "KARIN_OFFICE";
-static const char *const kPcSpeaker = "PC";
-static const char *const kEdnaNpc = "EDNA";
static const DialogueLineEntry kKarinCem10AliveLines[] = {
- { 0x10a5, kPcSpeaker, 4 },
- { 0x10a9, kKarinNpc, 3 },
- { 0x10ae, kPcSpeaker, 2 },
- { 0x10b2, kKarinNpc, 3 },
- { 0x10b6, kPcSpeaker, 0 },
- { 0x10ba, kKarinNpc, 3 },
- { 0x10bf, kPcSpeaker, 0 },
- { 0x10c3, kKarinNpc, 3 }
+ { 0x10a5, "PC", 4 },
+ { 0x10a9, "KARIN", 3 },
+ { 0x10ae, "PC", 2 },
+ { 0x10b2, "KARIN", 3 },
+ { 0x10b6, "PC", 0 },
+ { 0x10ba, "KARIN", 3 },
+ { 0x10bf, "PC", 0 },
+ { 0x10c3, "KARIN", 3 }
};
static const DialogueLineEntry kKarinFirstNoItemLines[] = {
- { 0x1076, kPcSpeaker, 1 },
- { 0x107a, kKarinNpc, 1 },
- { 0x107e, kPcSpeaker, 1 },
- { 0x1082, kKarinNpc, 1 },
- { 0x1087, kPcSpeaker, 0 },
- { 0x108b, kKarinNpc, 1 }
+ { 0x1076, "PC", 1 },
+ { 0x107a, "KARIN", 1 },
+ { 0x107e, "PC", 1 },
+ { 0x1082, "KARIN", 1 },
+ { 0x1087, "PC", 0 },
+ { 0x108b, "KARIN", 1 }
};
static const DialogueLineEntry kKarinFirstPhotoReplyLines[] = {
- { 0x10e3, kKarinNpc, 4 },
- { 0x10e7, kEdnaNpc, 2 }
+ { 0x10e3, "KARIN", 4 },
+ { 0x10e7, "EDNA", 2 }
};
static const DialogueLineEntry kKarinInvMagLines[] = {
- { 0x10ee, kKarinNpc, 0 },
- { 0x10f2, kEdnaNpc, 2 }
+ { 0x10ee, "KARIN", 0 },
+ { 0x10f2, "EDNA", 2 }
};
} // End of namespace
-bool KarinDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kKarinNpc) ||
- npcName.equalsIgnoreCase(kKarinStandingNpc) ||
- npcName.equalsIgnoreCase(kKarinCem10Npc) ||
- npcName.equalsIgnoreCase(kKarinOfficeNpc);
-}
-
Common::Error KarinDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
KarinRoomDialogueState &state = _state;
- auto playKarinLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kKarinNpc, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
- auto executeActionTagIfSet = [&](const char *tag) {
- InteractionResult interaction;
- if (!runtime.executeActionTag(tag, interaction))
- return;
-
- runtime.applyImmediateDialogueInteractionEffects(interaction);
- runtime.queueDialogueInteractionIfNeeded(interaction);
- };
const bool karinFoundAlive = runtime.startupScript().getFlagValue("KARIN_FOUND_ALIVE");
if (karinFoundAlive && runtime.startupScript().getFlagValue("IN_CEM10") &&
!state.cem10AliveLinePlayed) {
state.cem10AliveLinePlayed = true;
- return playSequence(kKarinCem10AliveLines, ARRAYSIZE(kKarinCem10AliveLines));
+ return runtime.playDialogueEntrySequence(kKarinCem10AliveLines, ARRAYSIZE(kKarinCem10AliveLines));
}
if (usedItemName.empty()) {
if (!karinFoundAlive && !state.notFoundAliveLinePlayed) {
state.notFoundAliveLinePlayed = true;
- Common::Error lineError = playSequence(
- kKarinFirstNoItemLines, ARRAYSIZE(kKarinFirstNoItemLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kKarinFirstNoItemLines,
+ ARRAYSIZE(kKarinFirstNoItemLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- return playKarinLine(0x10dc);
+ return runtime.playDialogueLineWithVariant(0x10dc, "KARIN", 0);
}
const bool photoEvidence = usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
@@ -121,36 +94,36 @@ Common::Error KarinDialogueHandler::handleDialogue(DialogueRuntime &runtime,
else
sharedState.discussedCasketPhotoEvidence = 1;
- Common::Error lineError = playSequence(
- kKarinFirstPhotoReplyLines, ARRAYSIZE(kKarinFirstPhotoReplyLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kKarinFirstPhotoReplyLines,
+ ARRAYSIZE(kKarinFirstPhotoReplyLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- runtime.setActiveSpeakerPortrait(kKarinNpc, 0);
+ runtime.setActiveSpeakerPortrait("KARIN", 0);
state.photoReplyOverrideFlag = true;
return Common::kNoError;
}
- Common::Error lineError = playKarinLine(0x10e3, 4);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x10e3, "KARIN", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)runtime.startupScript().setRuntimeFlagValue("DNALFT_PERVERT", true);
- executeActionTagIfSet("CALL_POLICE");
+ runtime.executeAndQueueAction("CALL_POLICE");
return Common::kNoError;
}
if (usedItemName.equalsIgnoreCase("INV_MAG")) {
- Common::Error lineError = playSequence(kKarinInvMagLines, ARRAYSIZE(kKarinInvMagLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kKarinInvMagLines, ARRAYSIZE(kKarinInvMagLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)runtime.startupScript().setRuntimeFlagValue("DNALFT_PERVERT", true);
- executeActionTagIfSet("CALL_POLICE");
+ runtime.executeAndQueueAction("CALL_POLICE");
return Common::kNoError;
}
- return playKarinLine(0x10d6, 1);
+ return runtime.playDialogueLineWithVariant(0x10d6, "KARIN", 1);
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/karin_dialogue.h b/engines/harvester/npc/karin_dialogue.h
index 7ef62b48bee..f10dfe27b72 100644
--- a/engines/harvester/npc/karin_dialogue.h
+++ b/engines/harvester/npc/karin_dialogue.h
@@ -34,7 +34,6 @@ public:
bool notFoundAliveLinePlayed = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = KarinRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.photoReplyOverrideFlag);
diff --git a/engines/harvester/npc/librarian_dialogue.cpp b/engines/harvester/npc/librarian_dialogue.cpp
index 3de15fb9664..0da747d80bf 100644
--- a/engines/harvester/npc/librarian_dialogue.cpp
+++ b/engines/harvester/npc/librarian_dialogue.cpp
@@ -29,42 +29,36 @@ namespace Harvester {
namespace {
-static const char *const kLibrarianNpc = "LIBRARIAN";
-static const char *const kPcSpeaker = "PC";
static const char *const kRahRoomName = "RAH";
static const int kLibrarianResponseLineIndex = 0xfa;
static const DialogueLineEntry kLibrarianCainbookTradeLines[] = {
- { 0x1db1, kLibrarianNpc, 1 },
- { 0x1db7, kPcSpeaker, 0 },
- { 0x1dbb, kLibrarianNpc, 0 },
- { 0x1dc2, kPcSpeaker, 4 },
- { 0x1dc6, kLibrarianNpc, 0 }
+ { 0x1db1, "LIBRARIAN", 1 },
+ { 0x1db7, "PC", 0 },
+ { 0x1dbb, "LIBRARIAN", 0 },
+ { 0x1dc2, "PC", 4 },
+ { 0x1dc6, "LIBRARIAN", 0 }
};
static const DialogueLineEntry kLibrarianIntroLines[] = {
- { 0x1d5b, kLibrarianNpc, 0 },
- { 0x1d5f, kPcSpeaker, 0 },
- { 0x1d63, kLibrarianNpc, 2 },
- { 0x1d67, kPcSpeaker, 0 },
- { 0x1d6c, kLibrarianNpc, 0 },
- { 0x1d77, kLibrarianNpc, 0 }
+ { 0x1d5b, "LIBRARIAN", 0 },
+ { 0x1d5f, "PC", 0 },
+ { 0x1d63, "LIBRARIAN", 2 },
+ { 0x1d67, "PC", 0 },
+ { 0x1d6c, "LIBRARIAN", 0 },
+ { 0x1d77, "LIBRARIAN", 0 }
};
static const DialogueLineEntry kLibrarianNoItemFollowupLines[] = {
- { 0x1d8f, kLibrarianNpc, 0 },
- { 0x1d94, kPcSpeaker, 0 },
- { 0x1d98, kLibrarianNpc, 0 },
- { 0x1da1, kPcSpeaker, 0 },
- { 0x1da5, kLibrarianNpc, 0 }
+ { 0x1d8f, "LIBRARIAN", 0 },
+ { 0x1d94, "PC", 0 },
+ { 0x1d98, "LIBRARIAN", 0 },
+ { 0x1da1, "PC", 0 },
+ { 0x1da5, "LIBRARIAN", 0 }
};
} // End of namespace
-bool LibrarianDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kLibrarianNpc);
-}
-
Common::Error LibrarianDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &) {
auto hasVisibleInventoryItem = [&](const char *objectName) {
@@ -77,14 +71,12 @@ Common::Error LibrarianDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return false;
};
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+
auto completeCainbookTrade = [&]() -> Common::Error {
(void)runtime.startupScript().addRuntimeObjectToInventory("CLUE");
- Common::Error lineError = playSequence(
- kLibrarianCainbookTradeLines, ARRAYSIZE(kLibrarianCainbookTradeLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kLibrarianCainbookTradeLines,
+ ARRAYSIZE(kLibrarianCainbookTradeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -98,12 +90,12 @@ Common::Error LibrarianDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!usedItemName.empty()) {
if (!usedItemName.equalsIgnoreCase("CAINBOOK"))
- return runtime.playDialogueLine(0x1d5b, kLibrarianNpc);
+ return runtime.playDialogueLine(0x1d5b, "LIBRARIAN");
return completeCainbookTrade();
}
- Common::Error lineError = playSequence(kLibrarianIntroLines, ARRAYSIZE(kLibrarianIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kLibrarianIntroLines, ARRAYSIZE(kLibrarianIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -113,16 +105,16 @@ Common::Error LibrarianDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = runtime.playDialogueLine(0x1d85, kLibrarianNpc);
+ lineError = runtime.playDialogueLine(0x1d85, "LIBRARIAN");
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = runtime.playDialogueLineWithVariant(0x1d8b, kLibrarianNpc, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x1d8b, "LIBRARIAN", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- return playSequence(kLibrarianNoItemFollowupLines, ARRAYSIZE(kLibrarianNoItemFollowupLines));
+ return runtime.playDialogueEntrySequence(kLibrarianNoItemFollowupLines, ARRAYSIZE(kLibrarianNoItemFollowupLines));
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/librarian_dialogue.h b/engines/harvester/npc/librarian_dialogue.h
index fe4a0d4ec14..01eb4b021a9 100644
--- a/engines/harvester/npc/librarian_dialogue.h
+++ b/engines/harvester/npc/librarian_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class LibrarianDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/lodge_chef_dialogue.cpp b/engines/harvester/npc/lodge_chef_dialogue.cpp
index b385e4dc225..28ad8b546e5 100644
--- a/engines/harvester/npc/lodge_chef_dialogue.cpp
+++ b/engines/harvester/npc/lodge_chef_dialogue.cpp
@@ -28,28 +28,22 @@ namespace Harvester {
namespace {
-static const char *const kLodgeChefNpc = "LODGE_CHEF";
-static const char *const kPcSpeaker = "PC";
static const int kLodgeChefResponseLine = 0x21;
static const DialogueLineEntry kLodgeChefIntroLines[] = {
- { 0x1b10, kLodgeChefNpc, 2 },
- { 0x1b19, kLodgeChefNpc, 0 },
- { 0x1b1a, kLodgeChefNpc, 3 },
- { 0x1b1b, kLodgeChefNpc, 0 }
+ { 0x1b10, "LODGE_CHEF", 2 },
+ { 0x1b19, "LODGE_CHEF", 0 },
+ { 0x1b1a, "LODGE_CHEF", 3 },
+ { 0x1b1b, "LODGE_CHEF", 0 }
};
static const DialogueLineEntry kLodgeChefTailLines[] = {
- { 0x1b36, kPcSpeaker, 0 },
- { 0x1b3a, kLodgeChefNpc, 3 }
+ { 0x1b36, "PC", 0 },
+ { 0x1b3a, "LODGE_CHEF", 3 }
};
} // End of namespace
-bool LodgeChefDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kLodgeChefNpc);
-}
-
Common::Error LodgeChefDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
Common::Error lineError = runtime.playDialogueEntrySequence(
@@ -64,9 +58,9 @@ Common::Error LodgeChefDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = runtime.playDialogueLineWithVariant(0x1b2c, kLodgeChefNpc, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x1b2c, "LODGE_CHEF", 3);
} else if (responseIndex == 2) {
- lineError = runtime.playDialogueLineWithVariant(0x1b31, kLodgeChefNpc, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x1b31, "LODGE_CHEF", 0);
} else {
lineError = Common::kNoError;
}
diff --git a/engines/harvester/npc/lodge_chef_dialogue.h b/engines/harvester/npc/lodge_chef_dialogue.h
index b0d3a563571..eaeb1793358 100644
--- a/engines/harvester/npc/lodge_chef_dialogue.h
+++ b/engines/harvester/npc/lodge_chef_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class LodgeChefDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/loomis_dialogue.cpp b/engines/harvester/npc/loomis_dialogue.cpp
index 726d74c312c..101f8dbf22f 100644
--- a/engines/harvester/npc/loomis_dialogue.cpp
+++ b/engines/harvester/npc/loomis_dialogue.cpp
@@ -30,8 +30,6 @@ namespace Harvester {
namespace {
static const int kLoomisSheriffTopicLineIndices[] = { 0x5f, 0x60, 0x61 };
-static const char *const kLoomisNpc = "LOOMIS";
-static const char *const kPcSpeaker = "PC";
static const char *const kLoomisTopicAlias = "LOOMIS";
static const char *const kPhelpsTopicAlias = "Phelps";
static const char *const kMensNeedsTopicAlias = "Man's Needs";
@@ -39,61 +37,42 @@ static const char *const kPcFryDaddyActionTag = "PC_FRY_DADDY_1";
static const char *const kDialogueC048FstPath = "GRAPHIC/FST/C048.FST";
static const DialogueLineEntry kLoomisIntroOpeningLines[] = {
- { 0x10fd, kLoomisNpc, 0 },
- { 0x1101, kPcSpeaker, 0 },
- { 0x1105, kLoomisNpc, 0 },
- { 0x110a, kPcSpeaker, 0 },
- { 0x110e, kLoomisNpc, 0 }
+ { 0x10fd, "LOOMIS", 0 },
+ { 0x1101, "PC", 0 },
+ { 0x1105, "LOOMIS", 0 },
+ { 0x110a, "PC", 0 },
+ { 0x110e, "LOOMIS", 0 }
};
static const DialogueLineEntry kLoomisReturnVisitFollowupLines[] = {
- { 0x11a8, kLoomisNpc, 1 },
- { 0x11ac, kPcSpeaker, 0 },
- { 0x11b0, kLoomisNpc, 3 }
+ { 0x11a8, "LOOMIS", 1 },
+ { 0x11ac, "PC", 0 },
+ { 0x11b0, "LOOMIS", 3 }
};
static const DialogueLineEntry kLoomisMrsLoomisLines[] = {
- { 0x114f, kLoomisNpc, 1 },
- { 0x1150, kLoomisNpc, 2 },
- { 0x1151, kLoomisNpc, 2 },
- { 0x1152, kLoomisNpc, 2 },
- { 0x1153, kLoomisNpc, 3 }
+ { 0x114f, "LOOMIS", 1 },
+ { 0x1150, "LOOMIS", 2 },
+ { 0x1151, "LOOMIS", 2 },
+ { 0x1152, "LOOMIS", 2 },
+ { 0x1153, "LOOMIS", 3 }
};
static const DialogueLineEntry kLoomisMrsPhelpsLines[] = {
- { 0x1161, kLoomisNpc, 0 },
- { 0x1162, kLoomisNpc, 3 },
- { 0x1163, kLoomisNpc, 3 }
+ { 0x1161, "LOOMIS", 0 },
+ { 0x1162, "LOOMIS", 3 },
+ { 0x1163, "LOOMIS", 3 }
};
} // End of namespace
-bool LoomisDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("LOOMIS");
-}
-
Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
LoomisRoomDialogueState &state = _state;
Common::String &loomisTopicBuffer = state.currentTopicBuffer;
int &loomisTopicBufferLineIndex = state.currentTopicBufferLineIndex;
- auto assignLoomisTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(loomisTopicBuffer, loomisTopicBufferLineIndex,
- responseLineIndex, "Loomis topic buffer");
- };
- auto playLoomisLine = [&](int wavId, const char *speakerId = kLoomisNpc,
- int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, speakerId, headVariant);
- };
- auto executeLoomisActionTag = [&](const char *tag) {
- InteractionResult interaction;
- if (!runtime.executeActionTag(tag, interaction))
- return;
-
- runtime.applyImmediateDialogueInteractionEffects(interaction);
- runtime.queueDialogueInteractionIfNeeded(interaction);
- };
+ DialogueTopicBuffer topics(runtime, loomisTopicBuffer, loomisTopicBufferLineIndex, "Loomis topic buffer");
if (usedItemName.empty()) {
Common::Error lineError = Common::kNoError;
@@ -109,16 +88,16 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.dialogueStateD2f04 = true;
if (runtime.startupScript().getFlagValue("SHERIFF_IN_DINER")) {
- lineError = playLoomisLine(0x1112, kPcSpeaker);
+ lineError = runtime.playDialogueLineWithVariant(0x1112, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playLoomisLine(0x1118);
+ lineError = runtime.playDialogueLineWithVariant(0x1118, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
}
- lineError = playLoomisLine(0x1121);
+ lineError = runtime.playDialogueLineWithVariant(0x1121, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -127,7 +106,7 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
- lineError = playLoomisLine(0x1130, kLoomisNpc, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x1130, "LOOMIS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (state.returnVisitFollowupPending) {
@@ -137,7 +116,7 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
} else {
- lineError = playLoomisLine(0x11f6);
+ lineError = runtime.playDialogueLineWithVariant(0x11f6, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -145,19 +124,19 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephMidgameShown) {
state.stephMidgameShown = true;
- lineError = playLoomisLine(0x1230, kLoomisNpc, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x1230, "LOOMIS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getCurrentStoryDayIndex() == 5 &&
!state.dayFiveShown) {
state.dayFiveShown = true;
- lineError = playLoomisLine(0x123c);
+ lineError = runtime.playDialogueLineWithVariant(0x123c, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- assignLoomisTopicBuffer(0x54);
+ topics.assign(0x54);
for (;;) {
Common::String selectedTopic;
Common::Error menuError = runtime.runKeywordMenu(
@@ -169,14 +148,14 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (selectedTopic.equalsIgnoreCase(runtime.genericByeTopic()) ||
runtime.matchesResponseLine(selectedTopic, 0x56)) {
- return playLoomisLine(0x11a1, kLoomisNpc, 1);
+ return runtime.playDialogueLineWithVariant(0x11a1, "LOOMIS", 1);
}
if (runtime.matchesResponseLine(selectedTopic, 0x57)) {
- lineError = playLoomisLine(0x1143, kLoomisNpc, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1143, "LOOMIS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignLoomisTopicBuffer(0x58);
+ topics.assign(0x58);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x59) ||
@@ -185,7 +164,7 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
kLoomisMrsLoomisLines, ARRAYSIZE(kLoomisMrsLoomisLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignLoomisTopicBuffer(0x5a);
+ topics.assign(0x5a);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x5b) ||
@@ -194,34 +173,34 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
kLoomisMrsPhelpsLines, ARRAYSIZE(kLoomisMrsPhelpsLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignLoomisTopicBuffer(0x5c);
+ topics.assign(0x5c);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x5d) ||
selectedTopic.equalsIgnoreCase(kMensNeedsTopicAlias)) {
- lineError = playLoomisLine(0x1170, kLoomisNpc, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1170, "LOOMIS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignLoomisTopicBuffer(0x5e);
+ topics.assign(0x5e);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic,
kLoomisSheriffTopicLineIndices, ARRAYSIZE(kLoomisSheriffTopicLineIndices))) {
- lineError = playLoomisLine(0x117e);
+ lineError = runtime.playDialogueLineWithVariant(0x117e, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignLoomisTopicBuffer(0x62);
+ topics.assign(0x62);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x63)) {
- lineError = playLoomisLine(0x118a);
+ lineError = runtime.playDialogueLineWithVariant(0x118a, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignLoomisTopicBuffer(0x64);
+ topics.assign(0x64);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x65)) {
- lineError = playLoomisLine(0x1196, kLoomisNpc, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1196, "LOOMIS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
@@ -229,7 +208,7 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0x66))
continue;
- lineError = playLoomisLine(0x11fc);
+ lineError = runtime.playDialogueLineWithVariant(0x11fc, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -243,7 +222,7 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("TV_DEED_PHOTOCOPY")) {
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
sharedState.discussedNoteCheckbookEvidence = 1;
- Common::Error lineError = playLoomisLine(0x1209);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1209, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -253,20 +232,20 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playLoomisLine(0x1214);
+ lineError = runtime.playDialogueLineWithVariant(0x1214, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playLoomisLine(0x1219);
+ lineError = runtime.playDialogueLineWithVariant(0x1219, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playLoomisLine(0x121f, kLoomisNpc, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x121f, "LOOMIS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeLoomisActionTag(kPcFryDaddyActionTag);
+ runtime.executeAndQueueAction(kPcFryDaddyActionTag);
return Common::kNoError;
}
if ((usedItemName.equalsIgnoreCase("LEDGER") ||
@@ -274,15 +253,15 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
runtime.startupScript().getFlagValue("HAVE_BOTH_LEDGERS")) {
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownLedgersToAnyone, true);
sharedState.discussedLedgerEvidence = 1;
- return playLoomisLine(0x1229);
+ return runtime.playDialogueLineWithVariant(0x1229, "LOOMIS", 0);
}
if (usedItemName.equalsIgnoreCase("INV_MAG")) {
if (!runtime.startupScript().getFlagValue("SHERIFF_IN_DINER")) {
(void)runtime.startupScript().addRuntimeObjectToInventory("INV_MAG");
- return playLoomisLine(0x11db, kLoomisNpc, 1);
+ return runtime.playDialogueLineWithVariant(0x11db, "LOOMIS", 1);
}
- Common::Error lineError = playLoomisLine(0x11bb);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x11bb, "LOOMIS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -292,7 +271,7 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playLoomisLine(0x11c6, kLoomisNpc, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x11c6, "LOOMIS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -316,13 +295,13 @@ Common::Error LoomisDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)runtime.startupScript().addRuntimeObjectToInventory("INV_MAG");
if (responseIndex == 2)
- return playLoomisLine(0x11cc, kLoomisNpc, 3);
+ return runtime.playDialogueLineWithVariant(0x11cc, "LOOMIS", 3);
return Common::kNoError;
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL"))
- return playLoomisLine(0x1143, kLoomisNpc, 1);
+ return runtime.playDialogueLineWithVariant(0x1143, "LOOMIS", 1);
- return playLoomisLine(0x1202);
+ return runtime.playDialogueLineWithVariant(0x1202, "LOOMIS", 0);
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/loomis_dialogue.h b/engines/harvester/npc/loomis_dialogue.h
index a340151260a..1a7313873e7 100644
--- a/engines/harvester/npc/loomis_dialogue.h
+++ b/engines/harvester/npc/loomis_dialogue.h
@@ -37,7 +37,6 @@ public:
bool dayFiveShown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = LoomisRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueString(s, _state.currentTopicBuffer);
diff --git a/engines/harvester/npc/madam_dialogue.cpp b/engines/harvester/npc/madam_dialogue.cpp
index cc6870879b0..cee280493f4 100644
--- a/engines/harvester/npc/madam_dialogue.cpp
+++ b/engines/harvester/npc/madam_dialogue.cpp
@@ -28,8 +28,6 @@ namespace Harvester {
namespace {
-static const char *const kMadamNpc = "MADAM";
-static const char *const kPcSpeaker = "PC";
static const char *const kHookerNpc = "HOOKER";
static const char *const kBarCash200ItemName = "BARCASH200";
static const char *const kInventoryOwnerName = "INVENTORY";
@@ -43,18 +41,8 @@ static const int kMadamPaymentResponseLine = 0xfc;
} // End of namespace
-bool MadamDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kMadamNpc);
-}
-
Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
- auto playMadamLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kMadamNpc, headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kPcSpeaker, headVariant);
- };
auto queueHookerMonsterfyTransition = [&]() {
InteractionResult interaction;
if (runtime.startupScript().queueRuntimeNpcDeathOrMonsterfy(kHookerNpc)) {
@@ -79,7 +67,7 @@ Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
(void)runtime.startupScript().setRuntimeFlagValue(kMadamInterruptFlag, false);
- Common::Error lineError = playMadamLine(0x1537, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1537, "MADAM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -89,11 +77,11 @@ Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex != 1) {
- lineError = playMadamLine(0x1577);
+ lineError = runtime.playDialogueLineWithVariant(0x1577, "MADAM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMadamLine(0x157b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x157b, "MADAM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -101,20 +89,20 @@ Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
}
- lineError = playMadamLine(0x1542, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1542, "MADAM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!runtime.startupScript().isObjectInInventory(kBarCash200ItemName)) {
- lineError = playPcLine(0x156e);
+ lineError = runtime.playDialogueLineWithVariant(0x156e, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMadamLine(0x1572);
+ lineError = runtime.playDialogueLineWithVariant(0x1572, "MADAM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMadamLine(0x157b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x157b, "MADAM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -128,11 +116,11 @@ Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMadamLine(0x154e);
+ lineError = runtime.playDialogueLineWithVariant(0x154e, "MADAM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMadamLine(0x157b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x157b, "MADAM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -142,7 +130,7 @@ Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseIndex != 2)
return Common::kNoError;
- lineError = playMadamLine(0x1555, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1555, "MADAM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -153,11 +141,11 @@ Common::Error MadamDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMadamLine(0x155a);
+ lineError = runtime.playDialogueLineWithVariant(0x155a, "MADAM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMadamLine(0x1563);
+ lineError = runtime.playDialogueLineWithVariant(0x1563, "MADAM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
diff --git a/engines/harvester/npc/madam_dialogue.h b/engines/harvester/npc/madam_dialogue.h
index 3dc37f955c8..efd54b10f0e 100644
--- a/engines/harvester/npc/madam_dialogue.h
+++ b/engines/harvester/npc/madam_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class MadamDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/maint_man_dialogue.cpp b/engines/harvester/npc/maint_man_dialogue.cpp
index d95720e643c..36b871f295d 100644
--- a/engines/harvester/npc/maint_man_dialogue.cpp
+++ b/engines/harvester/npc/maint_man_dialogue.cpp
@@ -28,17 +28,12 @@ namespace Harvester {
namespace {
-static const char *const kMaintManNpc = "MAINT_MAN";
static const char *const kMaintManFirstConversationFlag = "MAINTENANCE_MAN_FIRST_CONVERSATION";
static const char *const kMaintManThirdConversationFlag = "MAINTENANCE_MAN_THIRD_CONVERSATION";
static const char *const kMaintManFourthConversationFlag = "MAINTENANCE_MAN_FOURTH_CONVERSATION";
} // End of namespace
-bool MaintManDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kMaintManNpc);
-}
-
Common::Error MaintManDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
int wavId = 0xdb6;
@@ -48,15 +43,15 @@ Common::Error MaintManDialogueHandler::handleDialogue(DialogueRuntime &runtime,
wavId = 0xdaf;
headVariant = 1;
} else if (runtime.startupScript().getFlagValue(kMaintManThirdConversationFlag)) {
- return runtime.playDialogueLineWithVariant(0xdbc, kMaintManNpc, 2);
+ return runtime.playDialogueLineWithVariant(0xdbc, "MAINT_MAN", 2);
} else if (runtime.startupScript().getFlagValue(kMaintManFourthConversationFlag)) {
- return runtime.playDialogueLineWithVariant(0xdc4, kMaintManNpc, 2);
+ return runtime.playDialogueLineWithVariant(0xdc4, "MAINT_MAN", 2);
}
if (headVariant != 0)
- return runtime.playDialogueLineWithVariant(wavId, kMaintManNpc, headVariant);
+ return runtime.playDialogueLineWithVariant(wavId, "MAINT_MAN", headVariant);
- return runtime.playDialogueLine(wavId, kMaintManNpc);
+ return runtime.playDialogueLine(wavId, "MAINT_MAN");
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/maint_man_dialogue.h b/engines/harvester/npc/maint_man_dialogue.h
index 0b08e377c7d..137fbcc24f5 100644
--- a/engines/harvester/npc/maint_man_dialogue.h
+++ b/engines/harvester/npc/maint_man_dialogue.h
@@ -28,7 +28,6 @@ namespace Harvester {
class MaintManDialogueHandler : public NpcDialogueHandler {
public:
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {}
Common::Error handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) override;
diff --git a/engines/harvester/npc/mcknight_dialogue.cpp b/engines/harvester/npc/mcknight_dialogue.cpp
index 8bebe53b3c7..8afd3e0eb01 100644
--- a/engines/harvester/npc/mcknight_dialogue.cpp
+++ b/engines/harvester/npc/mcknight_dialogue.cpp
@@ -29,55 +29,34 @@
namespace Harvester {
-namespace {
-
-static const char *const kMcknightNpc = "MCKNIGHT";
-static const char *const kPcSpeaker = "PC";
-
-} // End of namespace
-
-bool McknightDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kMcknightNpc);
-}
-
Common::Error McknightDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
- auto playMcknightLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kMcknightNpc, headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kPcSpeaker, headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
-
if (runtime.startupScript().getFlagValue("LOOK_SAFE_2ND"))
- return playMcknightLine(0x15d0, 2);
+ return runtime.playDialogueLineWithVariant(0x15d0, "MCKNIGHT", 2);
if (runtime.startupScript().getFlagValue("LOOK_SAFE_1ST") && !_state.lookSafeFirstLineGate) {
_state.lookSafeFirstLineGate = true;
- return playMcknightLine(0x15c9, 2);
+ return runtime.playDialogueLineWithVariant(0x15c9, "MCKNIGHT", 2);
}
if (usedItemName.empty()) {
if (_state.talkStatePending) {
_state.talkStatePending = false;
const DialogueLineEntry lines[] = {
- { 0x1587, kMcknightNpc, 2 },
- { 0x158b, kPcSpeaker, 0 },
- { 0x158f, kMcknightNpc, 0 },
- { 0x1594, kPcSpeaker, 0 },
- { 0x1598, kMcknightNpc, 2 }
+ { 0x1587, "MCKNIGHT", 2 },
+ { 0x158b, "PC", 0 },
+ { 0x158f, "MCKNIGHT", 0 },
+ { 0x1594, "PC", 0 },
+ { 0x1598, "MCKNIGHT", 2 }
};
- Common::Error lineError = playSequence(lines, ARRAYSIZE(lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
- lineError = playPcLine(0x159d);
+ lineError = runtime.playDialogueLineWithVariant(0x159d, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMcknightLine(0x15a2, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x15a2, "MCKNIGHT", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
int responseIndex = 0;
@@ -85,50 +64,50 @@ Common::Error McknightDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1)
- return playMcknightLine(0x15af);
+ return runtime.playDialogueLineWithVariant(0x15af, "MCKNIGHT", 0);
if (responseIndex == 2) {
const DialogueLineEntry replyLines[] = {
- { 0x15b5, kMcknightNpc, 4 },
- { 0x15bd, kPcSpeaker, 0 },
- { 0x15c1, kMcknightNpc, 2 }
+ { 0x15b5, "MCKNIGHT", 4 },
+ { 0x15bd, "PC", 0 },
+ { 0x15c1, "MCKNIGHT", 2 }
};
- return playSequence(replyLines, ARRAYSIZE(replyLines));
+ return runtime.playDialogueEntrySequence(replyLines, ARRAYSIZE(replyLines));
}
}
- return playMcknightLine(0x15e4);
+ return runtime.playDialogueLineWithVariant(0x15e4, "MCKNIGHT", 0);
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
- return playMcknightLine(0x15ea, 1);
+ return runtime.playDialogueLineWithVariant(0x15ea, "MCKNIGHT", 1);
}
if (usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
sharedState.discussedCasketPhotoEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
- Common::Error lineError = playMcknightLine(0x15f2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x15f2, "MCKNIGHT", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2ebc) {
- lineError = playPcLine(0x15f8);
+ lineError = runtime.playDialogueLineWithVariant(0x15f8, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playMcknightLine(0x15fd);
+ return runtime.playDialogueLineWithVariant(0x15fd, "MCKNIGHT", 0);
}
- lineError = playPcLine(0x1605);
+ lineError = runtime.playDialogueLineWithVariant(0x1605, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playMcknightLine(0x1609);
+ return runtime.playDialogueLineWithVariant(0x1609, "MCKNIGHT", 0);
}
if ((usedItemName.equalsIgnoreCase("LEDGER") ||
usedItemName.equalsIgnoreCase("LEDGER2")) &&
runtime.startupScript().getFlagValue("HAVE_BOTH_LEDGERS")) {
sharedState.discussedLedgerEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownLedgersToAnyone, true);
- return playMcknightLine(0x1611, 1);
+ return runtime.playDialogueLineWithVariant(0x1611, "MCKNIGHT", 1);
}
if (usedItemName.equalsIgnoreCase("NOTE") ||
usedItemName.equalsIgnoreCase("NOTE_PHOTOCOPY") ||
@@ -137,16 +116,16 @@ Common::Error McknightDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedNoteCheckbookEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
const DialogueLineEntry lines[] = {
- { 0x161b, kMcknightNpc, 1 },
- { 0x1621, kPcSpeaker, 0 },
- { 0x1626, kMcknightNpc, 3 },
- { 0x162b, kPcSpeaker, 4 },
- { 0x1631, kMcknightNpc, 0 }
+ { 0x161b, "MCKNIGHT", 1 },
+ { 0x1621, "PC", 0 },
+ { 0x1626, "MCKNIGHT", 3 },
+ { 0x162b, "PC", 4 },
+ { 0x1631, "MCKNIGHT", 0 }
};
- return playSequence(lines, ARRAYSIZE(lines));
+ return runtime.playDialogueEntrySequence(lines, ARRAYSIZE(lines));
}
- return playMcknightLine(0x15de);
+ return runtime.playDialogueLineWithVariant(0x15de, "MCKNIGHT", 0);
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/mcknight_dialogue.h b/engines/harvester/npc/mcknight_dialogue.h
index df202a9d3ff..87cd2653757 100644
--- a/engines/harvester/npc/mcknight_dialogue.h
+++ b/engines/harvester/npc/mcknight_dialogue.h
@@ -33,7 +33,6 @@ public:
bool lookSafeFirstLineGate = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = McknightRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.talkStatePending);
diff --git a/engines/harvester/npc/memb_dir_dialogue.cpp b/engines/harvester/npc/memb_dir_dialogue.cpp
index 83db47e0b09..cfe9d8e2ad0 100644
--- a/engines/harvester/npc/memb_dir_dialogue.cpp
+++ b/engines/harvester/npc/memb_dir_dialogue.cpp
@@ -28,23 +28,14 @@ namespace Harvester {
namespace {
-static const char *const kMembDirNpc = "MEMB_DIR";
static const int kMembDirResponseLineIndex = 0xfe;
} // End of namespace
-bool MembDirDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kMembDirNpc);
-}
-
Common::Error MembDirDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
- auto playMembDirLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kMembDirNpc, headVariant);
- };
-
if (!runtime.startupScript().getFlagValue("PC_KILLED_KEWPIE")) {
- Common::Error lineError = playMembDirLine(0x2b7, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2b7, "MEMB_DIR", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -54,9 +45,9 @@ Common::Error MembDirDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1)
- return playMembDirLine(0x2c2);
+ return runtime.playDialogueLineWithVariant(0x2c2, "MEMB_DIR", 0);
if (responseIndex == 2)
- return playMembDirLine(0x2cb);
+ return runtime.playDialogueLineWithVariant(0x2cb, "MEMB_DIR", 0);
return Common::kNoError;
}
@@ -65,14 +56,14 @@ Common::Error MembDirDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return Common::kNoError;
_state.kewpieKillLinePlayed = true;
- Common::Error lineError = playMembDirLine(0x2d5, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2d5, "MEMB_DIR", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getFlagValue("TOOK_THE_DOLL"))
- return playMembDirLine(0x2e3);
+ return runtime.playDialogueLineWithVariant(0x2e3, "MEMB_DIR", 0);
- return playMembDirLine(0x2ea);
+ return runtime.playDialogueLineWithVariant(0x2ea, "MEMB_DIR", 0);
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/memb_dir_dialogue.h b/engines/harvester/npc/memb_dir_dialogue.h
index 4ca07624980..7cbaaf7fbf3 100644
--- a/engines/harvester/npc/memb_dir_dialogue.h
+++ b/engines/harvester/npc/memb_dir_dialogue.h
@@ -32,7 +32,6 @@ public:
bool kewpieKillLinePlayed = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = MembDirRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.kewpieKillLinePlayed);
diff --git a/engines/harvester/npc/mom_dialogue.cpp b/engines/harvester/npc/mom_dialogue.cpp
index 2bd2e8fa0aa..be474d65cae 100644
--- a/engines/harvester/npc/mom_dialogue.cpp
+++ b/engines/harvester/npc/mom_dialogue.cpp
@@ -474,36 +474,14 @@ static const int kMomGoodCauseDay5FollowupTopicBufferResponseLine = 0x15c;
} // End of namespace
-bool MomDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("MOM");
-}
-
Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
const int currentStoryDayIndex = runtime.startupScript().getCurrentStoryDayIndex();
MomRoomDialogueState &state = _state;
Common::String momTopicBuffer;
int momTopicBufferLineIndex = -1;
- auto assignMomTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(momTopicBuffer, momTopicBufferLineIndex,
- responseLineIndex, "Mom topic buffer");
- };
- auto playMomLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, "MOM", headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, "PC", headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
- auto executeActionTagIfSet = [&](const char *actionTag) {
- InteractionResult interaction;
- if (runtime.executeActionTag(actionTag, interaction)) {
- runtime.applyImmediateDialogueInteractionEffects(interaction);
- runtime.queueDialogueInteractionIfNeeded(interaction);
- }
- };
+ DialogueTopicBuffer topics(runtime, momTopicBuffer, momTopicBufferLineIndex, "Mom topic buffer");
+
auto hasInventoryObject = [&](const char *objectName) -> bool {
Common::Array<ObjectRecord> inventoryObjects;
runtime.startupScript().getVisibleInventoryObjects(inventoryObjects);
@@ -515,11 +493,11 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
};
auto runMomGoodbye = [&]() -> Common::Error {
if (!runtime.startupScript().getFlagValue("DAY_FLAG"))
- return playMomLine(0x256e, 1);
+ return runtime.playDialogueLineWithVariant(0x256e, "MOM", 1);
if (!runtime.startupScript().isNamedNpcDeathTypeClear("JIMMY"))
return Common::kNoError;
- return playMomLine(0x2051, 1);
+ return runtime.playDialogueLineWithVariant(0x2051, "MOM", 1);
};
if (!usedItemName.empty()) {
@@ -529,34 +507,34 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CHECKBOOK_PHOTOCOPY")) {
sharedState.discussedNoteCheckbookEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceOfBlackmail, true);
- return playMomLine(0x2317, 1);
+ return runtime.playDialogueLineWithVariant(0x2317, "MOM", 1);
}
if ((usedItemName.equalsIgnoreCase("LEDGER") ||
usedItemName.equalsIgnoreCase("LEDGER2")) &&
runtime.startupScript().getFlagValue("HAVE_BOTH_LEDGERS")) {
sharedState.discussedLedgerEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownLedgersToAnyone, true);
- return playSequence(kMomLedgerLines, ARRAYSIZE(kMomLedgerLines));
+ return runtime.playDialogueEntrySequence(kMomLedgerLines, ARRAYSIZE(kMomLedgerLines));
}
if (usedItemName.equalsIgnoreCase("CASKET_PHOTO") ||
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
sharedState.discussedCasketPhotoEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
- return playSequence(kMomCasketPhotoLines, ARRAYSIZE(kMomCasketPhotoLines));
+ return runtime.playDialogueEntrySequence(kMomCasketPhotoLines, ARRAYSIZE(kMomCasketPhotoLines));
}
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
- return playSequence(kMomWhaleyPhotoLines, ARRAYSIZE(kMomWhaleyPhotoLines));
+ return runtime.playDialogueEntrySequence(kMomWhaleyPhotoLines, ARRAYSIZE(kMomWhaleyPhotoLines));
}
if (usedItemName.equalsIgnoreCase("TV_DEED") ||
usedItemName.equalsIgnoreCase("TV_DEED_PHOTOCOPY")) {
sharedState.discussedTvDeedEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownEvidenceSheriffOwns, true);
- return playMomLine(0x2382, 1);
+ return runtime.playDialogueLineWithVariant(0x2382, "MOM", 1);
}
- return playMomLine(0x26cc, 2);
+ return runtime.playDialogueLineWithVariant(0x26cc, "MOM", 2);
}
if (state.introPending) {
@@ -566,17 +544,17 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.introDayIndex = currentStoryDayIndex;
sharedState.dialogueStateD2ef4 = true;
- Common::Error lineError = playSequence(kMomIntroLines, ARRAYSIZE(kMomIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomIntroLines, ARRAYSIZE(kMomIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomInitialTopicBufferResponseLine);
+ topics.assign(kMomInitialTopicBufferResponseLine);
} else if (state.sameDayIntroLineEnabled && currentStoryDayIndex == state.introDayIndex) {
- Common::Error lineError = playMomLine(0x2047, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2047, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomSameDayTopicBufferResponseLine);
+ topics.assign(kMomSameDayTopicBufferResponseLine);
} else if (state.postIntroDefaultLineEnabled) {
- Common::Error lineError = playMomLine(0x2311, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2311, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -585,18 +563,17 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.stephMidgameShown) {
state.stephMidgameShown = true;
- Common::Error lineError = playSequence(
- kMomStephMidgameOpeningLines, ARRAYSIZE(kMomStephMidgameOpeningLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomStephMidgameOpeningLines,
+ ARRAYSIZE(kMomStephMidgameOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC009FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(
- kMomStephMidgameClosingLines, ARRAYSIZE(kMomStephMidgameClosingLines));
+ lineError = runtime.playDialogueEntrySequence(kMomStephMidgameClosingLines, ARRAYSIZE(kMomStephMidgameClosingLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomStephMidgameTopicBufferResponseLine);
+ topics.assign(kMomStephMidgameTopicBufferResponseLine);
}
if (runtime.startupScript().getFlagValue("DINER_BURNED") &&
@@ -605,11 +582,11 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.dinerBurnedKarinMissingOrDeadShown) {
state.dinerBurnedKarinMissingOrDeadShown = true;
- Common::Error lineError = playMomLine(0x2456, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2456, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2ea4) {
- lineError = playMomLine(0x245d, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x245d, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -620,10 +597,10 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x246b, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x246b, "MOM", 0);
break;
case 2:
- lineError = playMomLine(0x246f, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x246f, "MOM", 1);
break;
default:
lineError = Common::kNoError;
@@ -638,8 +615,8 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
- Common::Error lineError = playSequence(
- kMomBurnedTvStationOpeningLines, ARRAYSIZE(kMomBurnedTvStationOpeningLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomBurnedTvStationOpeningLines,
+ ARRAYSIZE(kMomBurnedTvStationOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -648,25 +625,25 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
if (responseIndex == 1) {
- lineError = playMomLine(0x2237, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2237, "MOM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playSequence(
- kMomBurnedTvStationPreActionLines, ARRAYSIZE(kMomBurnedTvStationPreActionLines));
+ lineError = runtime.playDialogueEntrySequence(kMomBurnedTvStationPreActionLines,
+ ARRAYSIZE(kMomBurnedTvStationPreActionLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet(kBabyScreamActionTag);
- lineError = playSequence(
- kMomBurnedTvStationPreFstLines, ARRAYSIZE(kMomBurnedTvStationPreFstLines));
+ runtime.executeAndQueueAction(kBabyScreamActionTag);
+ lineError = runtime.playDialogueEntrySequence(kMomBurnedTvStationPreFstLines,
+ ARRAYSIZE(kMomBurnedTvStationPreFstLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC010FstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(
- kMomBurnedTvStationPostFstLines, ARRAYSIZE(kMomBurnedTvStationPostFstLines));
+ lineError = runtime.playDialogueEntrySequence(kMomBurnedTvStationPostFstLines,
+ ARRAYSIZE(kMomBurnedTvStationPostFstLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -674,7 +651,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("SCRATCHED_TUCKER") &&
!state.scratchedTuckerShown) {
state.scratchedTuckerShown = true;
- Common::Error lineError = playMomLine(0x23f3, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x23f3, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -682,8 +659,8 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("BARBER_POLE_STOLEN") &&
!state.barberPoleStolenShown) {
state.barberPoleStolenShown = true;
- Common::Error lineError = playSequence(
- kMomBarberPoleStolenLines, ARRAYSIZE(kMomBarberPoleStolenLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomBarberPoleStolenLines,
+ ARRAYSIZE(kMomBarberPoleStolenLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -694,8 +671,8 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
Common::Error lineError = runtime.startupScript().isNamedNpcDeathTypeClear("SPARKY") &&
runtime.startupScript().isNamedNpcDeathTypeClear("FIREMAN2")
- ? playSequence(kMomBoltOfClothClearLines, ARRAYSIZE(kMomBoltOfClothClearLines))
- : playSequence(kMomBoltOfClothDefaultLines, ARRAYSIZE(kMomBoltOfClothDefaultLines));
+ ? runtime.playDialogueEntrySequence(kMomBoltOfClothClearLines, ARRAYSIZE(kMomBoltOfClothClearLines))
+ : runtime.playDialogueEntrySequence(kMomBoltOfClothDefaultLines, ARRAYSIZE(kMomBoltOfClothDefaultLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -705,11 +682,11 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.dinerBurnedKarinAliveShown) {
state.dinerBurnedKarinAliveShown = true;
- Common::Error lineError = playMomLine(0x2434, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2434, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2ea4) {
- lineError = playMomLine(0x2439, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2439, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -720,10 +697,10 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x2448, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2448, "MOM", 0);
break;
case 2:
- lineError = playMomLine(0x244d, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x244d, "MOM", 1);
break;
default:
lineError = Common::kNoError;
@@ -737,8 +714,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("PC_ESCAPED_JAIL") &&
!state.escapedJailShown) {
state.escapedJailShown = true;
- Common::Error lineError = playSequence(
- kMomEscapedJailLines, ARRAYSIZE(kMomEscapedJailLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomEscapedJailLines, ARRAYSIZE(kMomEscapedJailLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -749,7 +725,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.karinKidnapedUnresolvedShown) {
state.karinKidnapedUnresolvedShown = true;
- Common::Error lineError = playMomLine(0x24d7, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x24d7, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.karinKidnapedDialogueState = true;
@@ -761,11 +737,10 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x24e3, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x24e3, "MOM", 0);
break;
case 2:
- lineError = playSequence(
- kMomKarinKidnappedResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomKarinKidnappedResponse2Lines,
ARRAYSIZE(kMomKarinKidnappedResponse2Lines));
break;
default:
@@ -780,8 +755,8 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.karinFoundAliveShown) {
state.karinFoundAliveShown = true;
- Common::Error lineError = playSequence(
- kMomKarinFoundAliveIntroLines, ARRAYSIZE(kMomKarinFoundAliveIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomKarinFoundAliveIntroLines,
+ ARRAYSIZE(kMomKarinFoundAliveIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -793,13 +768,13 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
lineError = runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED")
- ? playSequence(kMomKarinFoundAliveResponse1WithStephMidgameLines,
+ ? runtime.playDialogueEntrySequence(kMomKarinFoundAliveResponse1WithStephMidgameLines,
ARRAYSIZE(kMomKarinFoundAliveResponse1WithStephMidgameLines))
- : playSequence(kMomKarinFoundAliveResponse1WithoutStephMidgameLines,
+ : runtime.playDialogueEntrySequence(kMomKarinFoundAliveResponse1WithoutStephMidgameLines,
ARRAYSIZE(kMomKarinFoundAliveResponse1WithoutStephMidgameLines));
break;
case 2:
- lineError = playMomLine(0x2560, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2560, "MOM", 2);
break;
default:
lineError = Common::kNoError;
@@ -813,34 +788,34 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.karinFoundDeadShown) {
state.karinFoundDeadShown = true;
- Common::Error lineError = playMomLine(0x2576, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2576, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = hasInventoryObject("K_PURSE")
- ? playPcLine(0x257b, 0)
- : playPcLine(0x2580, 0);
+ ? runtime.playDialogueLineWithVariant(0x257b, "PC", 0)
+ : runtime.playDialogueLineWithVariant(0x2580, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x2585, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2585, "PC", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMomLine(0x258b, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x258b, "MOM", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (currentStoryDayIndex <= 5) {
- lineError = playMomLine(0x258f, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x258f, "MOM", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x2594, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2594, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMomLine(0x2598, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2598, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("DINER_BURNED") &&
!runtime.startupScript().isNamedNpcDeathTypeClear("EDNA")) {
- lineError = playMomLine(0x25a0, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x25a0, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -849,7 +824,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!runtime.startupScript().isNamedNpcDeathTypeClear("BUTCHER") &&
!state.butcherAbsentShown) {
state.butcherAbsentShown = true;
- Common::Error lineError = playMomLine(0x2633, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2633, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -857,16 +832,16 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!runtime.startupScript().isNamedNpcDeathTypeClear("MOYNAHAN") &&
!state.moynahanAbsentShown) {
state.moynahanAbsentShown = true;
- Common::Error lineError = playSequence(
- kMomMoynahanAbsentLines, ARRAYSIZE(kMomMoynahanAbsentLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomMoynahanAbsentLines,
+ ARRAYSIZE(kMomMoynahanAbsentLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (!runtime.startupScript().isNamedNpcDeathTypeClear("JIMMY")) {
Common::Error lineError = runtime.startupScript().getFlagValue("JIMMY_ATTACKED")
- ? playSequence(kMomJimmyAttackedLines, ARRAYSIZE(kMomJimmyAttackedLines))
- : playMomLine(0x266c, 0);
+ ? runtime.playDialogueEntrySequence(kMomJimmyAttackedLines, ARRAYSIZE(kMomJimmyAttackedLines))
+ : runtime.playDialogueLineWithVariant(0x266c, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!runtime.startupScript().getFlagValue("JIMMY_ATTACKED")) {
@@ -877,13 +852,13 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x2677, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2677, "MOM", 0);
break;
case 2:
- lineError = playMomLine(0x267b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x267b, "MOM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMomLine(0x267f, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x267f, "MOM", 3);
break;
default:
lineError = Common::kNoError;
@@ -897,7 +872,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!runtime.startupScript().isNamedNpcDeathTypeClear("WASP_WOMAN") &&
!state.waspWomanAbsentShown) {
state.waspWomanAbsentShown = true;
- Common::Error lineError = playMomLine(0x2689, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2689, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -906,8 +881,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephanieDeadPreMidgameShown) {
state.stephanieDeadPreMidgameShown = true;
- Common::Error lineError = playSequence(
- kMomStephanieDeadPreMidgameLines,
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomStephanieDeadPreMidgameLines,
ARRAYSIZE(kMomStephanieDeadPreMidgameLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -916,7 +890,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("DAY_5") && !state.day5Shown) {
state.day5Shown = true;
- Common::Error lineError = playSequence(kMomDay5Lines, ARRAYSIZE(kMomDay5Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomDay5Lines, ARRAYSIZE(kMomDay5Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -927,10 +901,10 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x20ce, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x20ce, "MOM", 1);
break;
case 2:
- lineError = playMomLine(0x2201, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2201, "MOM", 0);
break;
default:
lineError = Common::kNoError;
@@ -938,16 +912,16 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomDay5TopicBufferResponseLine);
+ topics.assign(kMomDay5TopicBufferResponseLine);
}
if (runtime.startupScript().getFlagValue("DAY_6") && !state.day6Shown) {
state.day6Shown = true;
- Common::Error lineError = playSequence(kMomDay6Lines, ARRAYSIZE(kMomDay6Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomDay6Lines, ARRAYSIZE(kMomDay6Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomDay6TopicBufferResponseLine);
+ topics.assign(kMomDay6TopicBufferResponseLine);
}
for (;;) {
@@ -962,147 +936,144 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return runMomGoodbye();
if (runtime.matchesResponseLine(selectedTopic, 0x116)) {
- Common::Error lineError = playSequence(kMomCookiesLines, ARRAYSIZE(kMomCookiesLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomCookiesLines, ARRAYSIZE(kMomCookiesLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x118);
+ topics.assign(0x118);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x119)) {
- Common::Error lineError = playSequence(kMomTopic119Lines, ARRAYSIZE(kMomTopic119Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic119Lines, ARRAYSIZE(kMomTopic119Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x11a);
+ topics.assign(0x11a);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x11d)) {
- Common::Error lineError = playSequence(
- kMomTopic11dOpeningLines, ARRAYSIZE(kMomTopic11dOpeningLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic11dOpeningLines,
+ ARRAYSIZE(kMomTopic11dOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC008AFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(
- kMomTopic11dPostC008ALines, ARRAYSIZE(kMomTopic11dPostC008ALines));
+ lineError = runtime.playDialogueEntrySequence(kMomTopic11dPostC008ALines, ARRAYSIZE(kMomTopic11dPostC008ALines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet(kBabyGurgleActionTag);
- lineError = playSequence(
- kMomTopic11dClosingLines, ARRAYSIZE(kMomTopic11dClosingLines));
+ runtime.executeAndQueueAction(kBabyGurgleActionTag);
+ lineError = runtime.playDialogueEntrySequence(kMomTopic11dClosingLines, ARRAYSIZE(kMomTopic11dClosingLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueFst(kDialogueC008BFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x120);
+ topics.assign(0x120);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x121)) {
- Common::Error lineError = playSequence(kMomTopic121Lines, ARRAYSIZE(kMomTopic121Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic121Lines, ARRAYSIZE(kMomTopic121Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.waspWomanDialogueState = true;
- assignMomTopicBuffer(0x122);
+ topics.assign(0x122);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x123)) {
- Common::Error lineError = playSequence(kMomSparkyLines, ARRAYSIZE(kMomSparkyLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomSparkyLines, ARRAYSIZE(kMomSparkyLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x124);
+ topics.assign(0x124);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMomPtaTopicResponseLines,
ARRAYSIZE(kMomPtaTopicResponseLines))) {
- Common::Error lineError = playSequence(kMomPtaLines, ARRAYSIZE(kMomPtaLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomPtaLines, ARRAYSIZE(kMomPtaLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomPtaFollowupTopicBufferResponseLine);
+ topics.assign(kMomPtaFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x12b)) {
- Common::Error lineError = playSequence(kMomTopic12bLines, ARRAYSIZE(kMomTopic12bLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic12bLines, ARRAYSIZE(kMomTopic12bLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x12c);
+ topics.assign(0x12c);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x12d)) {
- Common::Error lineError = playSequence(kMomTopic12dLines, ARRAYSIZE(kMomTopic12dLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic12dLines, ARRAYSIZE(kMomTopic12dLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x12e);
+ topics.assign(0x12e);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x12f)) {
- Common::Error lineError = playSequence(kMomTopic12fLines, ARRAYSIZE(kMomTopic12fLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic12fLines, ARRAYSIZE(kMomTopic12fLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x130);
+ topics.assign(0x130);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMomCookingTopicResponseLines,
ARRAYSIZE(kMomCookingTopicResponseLines))) {
- Common::Error lineError = playSequence(kMomCookingLines, ARRAYSIZE(kMomCookingLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomCookingLines, ARRAYSIZE(kMomCookingLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomCookingFollowupTopicBufferResponseLine);
+ topics.assign(kMomCookingFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x135)) {
- Common::Error lineError = playSequence(kMomTopic135Lines, ARRAYSIZE(kMomTopic135Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic135Lines, ARRAYSIZE(kMomTopic135Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x136);
+ topics.assign(0x136);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x137)) {
- Common::Error lineError = playSequence(kMomTopic137Lines, ARRAYSIZE(kMomTopic137Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic137Lines, ARRAYSIZE(kMomTopic137Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x13a)) {
- Common::Error lineError = playMomLine(0x1fa3, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x1fa3, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(0x13b);
+ topics.assign(0x13b);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x13c)) {
- Common::Error lineError = playSequence(
- kMomSlaughterhouseLines, ARRAYSIZE(kMomSlaughterhouseLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomSlaughterhouseLines,
+ ARRAYSIZE(kMomSlaughterhouseLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomSlaughterhouseFollowupTopicBufferResponseLine);
+ topics.assign(kMomSlaughterhouseFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x13f)) {
sharedState.momFatherTopicState = 1;
- Common::Error lineError = playSequence(kMomFatherLines, ARRAYSIZE(kMomFatherLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomFatherLines, ARRAYSIZE(kMomFatherLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getFlagValue("HEARD_DAD_MOAN")) {
- lineError = playSequence(
- kMomFatherHeardDadMoanLines, ARRAYSIZE(kMomFatherHeardDadMoanLines));
+ lineError = runtime.playDialogueEntrySequence(kMomFatherHeardDadMoanLines, ARRAYSIZE(kMomFatherHeardDadMoanLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- assignMomTopicBuffer(kMomFatherFollowupTopicBufferResponseLine);
+ topics.assign(kMomFatherFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x141)) {
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED")) {
- Common::Error lineError = playSequence(
- kMomStephMidgameLodgeLines, ARRAYSIZE(kMomStephMidgameLodgeLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomStephMidgameLodgeLines,
+ ARRAYSIZE(kMomStephMidgameLodgeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
sharedState.discussedLodgeTopic = true;
- Common::Error lineError = playSequence(kMomLodgeLines, ARRAYSIZE(kMomLodgeLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomLodgeLines, ARRAYSIZE(kMomLodgeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1113,16 +1084,16 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x1ffe, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x1ffe, "MOM", 1);
break;
case 2:
- lineError = playMomLine(0x2005, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2005, "MOM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x200a, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x200a, "PC", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMomLine(0x200e, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x200e, "MOM", 0);
break;
default:
lineError = Common::kNoError;
@@ -1130,19 +1101,19 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomLodgeFollowupTopicBufferResponseLine);
+ topics.assign(kMomLodgeFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMomBakeSaleTopicResponseLines,
ARRAYSIZE(kMomBakeSaleTopicResponseLines))) {
- Common::Error lineError = playSequence(kMomBakeSaleLines, ARRAYSIZE(kMomBakeSaleLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomBakeSaleLines, ARRAYSIZE(kMomBakeSaleLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomBakeSaleFollowupTopicBufferResponseLine);
+ topics.assign(kMomBakeSaleFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x14a)) {
- Common::Error lineError = playSequence(kMomTopic14aLines, ARRAYSIZE(kMomTopic14aLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic14aLines, ARRAYSIZE(kMomTopic14aLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
@@ -1150,7 +1121,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kMomPottsdamTopicResponseLines,
ARRAYSIZE(kMomPottsdamTopicResponseLines)) &&
runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED")) {
- Common::Error lineError = playMomLine(0x2086, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x2086, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1161,13 +1132,11 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playSequence(
- kMomPottsdamFirstResponse1Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamFirstResponse1Lines,
ARRAYSIZE(kMomPottsdamFirstResponse1Lines));
break;
case 2:
- lineError = playSequence(
- kMomPottsdamFirstResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamFirstResponse2Lines,
ARRAYSIZE(kMomPottsdamFirstResponse2Lines));
break;
default:
@@ -1177,8 +1146,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(
- kMomPottsdamCommonFollowupLines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamCommonFollowupLines,
ARRAYSIZE(kMomPottsdamCommonFollowupLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1190,8 +1158,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playSequence(
- kMomPottsdamSecondResponse1Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamSecondResponse1Lines,
ARRAYSIZE(kMomPottsdamSecondResponse1Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1203,13 +1170,11 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playSequence(
- kMomPottsdamThirdResponse1Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamThirdResponse1Lines,
ARRAYSIZE(kMomPottsdamThirdResponse1Lines));
break;
case 2:
- lineError = playSequence(
- kMomPottsdamThirdResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamThirdResponse2Lines,
ARRAYSIZE(kMomPottsdamThirdResponse2Lines));
break;
default:
@@ -1218,8 +1183,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
break;
case 2:
- lineError = playSequence(
- kMomPottsdamSecondResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kMomPottsdamSecondResponse2Lines,
ARRAYSIZE(kMomPottsdamSecondResponse2Lines));
break;
default:
@@ -1229,13 +1193,13 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignMomTopicBuffer(kMomPottsdamFollowupTopicBufferResponseLine);
+ topics.assign(kMomPottsdamFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMomMeatPlantTopicResponseLines,
ARRAYSIZE(kMomMeatPlantTopicResponseLines))) {
- Common::Error lineError = playSequence(
- kMomMeatPlantIntroLines, ARRAYSIZE(kMomMeatPlantIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomMeatPlantIntroLines,
+ ARRAYSIZE(kMomMeatPlantIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1246,14 +1210,10 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playSequence(
- kMomMeatPlantResponse1Lines,
- ARRAYSIZE(kMomMeatPlantResponse1Lines));
+ lineError = runtime.playDialogueEntrySequence(kMomMeatPlantResponse1Lines, ARRAYSIZE(kMomMeatPlantResponse1Lines));
break;
case 2:
- lineError = playSequence(
- kMomMeatPlantResponse2Lines,
- ARRAYSIZE(kMomMeatPlantResponse2Lines));
+ lineError = runtime.playDialogueEntrySequence(kMomMeatPlantResponse2Lines, ARRAYSIZE(kMomMeatPlantResponse2Lines));
break;
default:
lineError = Common::kNoError;
@@ -1262,66 +1222,63 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
if (responseIndex == 2)
- assignMomTopicBuffer(kMomMeatPlantFollowupTopicBufferResponseLine);
+ topics.assign(kMomMeatPlantFollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x155)) {
- Common::Error lineError = playSequence(kMomTopic155Lines, ARRAYSIZE(kMomTopic155Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic155Lines, ARRAYSIZE(kMomTopic155Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x156)) {
- Common::Error lineError = playSequence(kMomTopic156Lines, ARRAYSIZE(kMomTopic156Lines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic156Lines, ARRAYSIZE(kMomTopic156Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x15b) && currentStoryDayIndex == 5) {
Common::Error lineError = sharedState.momGoodCauseDay5State
- ? playSequence(kMomGoodCauseDay5CompleteLines,
- ARRAYSIZE(kMomGoodCauseDay5CompleteLines))
- : playSequence(kMomGoodCauseDay5FirstTimeLines,
- ARRAYSIZE(kMomGoodCauseDay5FirstTimeLines));
+ ? runtime.playDialogueEntrySequence(kMomGoodCauseDay5CompleteLines, ARRAYSIZE(kMomGoodCauseDay5CompleteLines))
+ : runtime.playDialogueEntrySequence(kMomGoodCauseDay5FirstTimeLines, ARRAYSIZE(kMomGoodCauseDay5FirstTimeLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.momGoodCauseDay5State &&
runtime.startupScript().getFlagValue(kSawSlashesOnBodyFlag)) {
- lineError = playSequence(
- kMomGoodCauseDay5SlashBodyLines,
+ lineError = runtime.playDialogueEntrySequence(kMomGoodCauseDay5SlashBodyLines,
ARRAYSIZE(kMomGoodCauseDay5SlashBodyLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (!sharedState.momGoodCauseDay5State)
- assignMomTopicBuffer(kMomGoodCauseDay5FollowupTopicBufferResponseLine);
+ topics.assign(kMomGoodCauseDay5FollowupTopicBufferResponseLine);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMomMoynahanTopicResponseLines,
ARRAYSIZE(kMomMoynahanTopicResponseLines))) {
- Common::Error lineError = playSequence(
- kMomMoynahanTopicLines, ARRAYSIZE(kMomMoynahanTopicLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomMoynahanTopicLines,
+ ARRAYSIZE(kMomMoynahanTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMomNewspaperFireTopicResponseLines,
ARRAYSIZE(kMomNewspaperFireTopicResponseLines))) {
- Common::Error lineError = playMomLine(0x229e, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x229e, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x16d)) {
- Common::Error lineError = playSequence(kMomTopic16dLines, ARRAYSIZE(kMomTopic16dLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMomTopic16dLines, ARRAYSIZE(kMomTopic16dLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x16e)) {
- Common::Error lineError = playMomLine(0x26a3, 0);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x26a3, "MOM", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1332,10 +1289,10 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
switch (responseIndex) {
case 1:
- lineError = playMomLine(0x26ae, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x26ae, "MOM", 0);
break;
case 2:
- lineError = playMomLine(0x26b3, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x26b3, "MOM", 2);
break;
default:
lineError = Common::kNoError;
@@ -1346,7 +1303,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return runMomGoodbye();
}
if (runtime.matchesResponseLine(selectedTopic, 0x170)) {
- Common::Error lineError = playMomLine(0x26bc, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x26bc, "MOM", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
@@ -1354,7 +1311,7 @@ Common::Error MomDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0x171))
continue;
- Common::Error lineError = playMomLine(0x26c6, 1);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x26c6, "MOM", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
diff --git a/engines/harvester/npc/mom_dialogue.h b/engines/harvester/npc/mom_dialogue.h
index 701ddab590a..60bedb30227 100644
--- a/engines/harvester/npc/mom_dialogue.h
+++ b/engines/harvester/npc/mom_dialogue.h
@@ -52,7 +52,6 @@ public:
bool day6Shown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = MomRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/mother_dialogue.cpp b/engines/harvester/npc/mother_dialogue.cpp
index e21c70bcb19..c526c750ff0 100644
--- a/engines/harvester/npc/mother_dialogue.cpp
+++ b/engines/harvester/npc/mother_dialogue.cpp
@@ -28,28 +28,19 @@ namespace Harvester {
namespace {
-static const char *const kMotherSpeakerId = "MOTHER";
static const char *const kDialogueC072FstPath = "GRAPHIC/FST/C072.FST";
static const char *const kDialogueC073FstPath = "GRAPHIC/FST/C073.FST";
} // End of namespace
-bool MotherDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("MOTHER");
-}
-
Common::Error MotherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &, DialogueSharedState &) {
if (!_state.talkStatePending)
return Common::kNoError;
- auto playMotherLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kMotherSpeakerId, headVariant);
- };
-
_state.talkStatePending = false;
- Common::Error lineError = playMotherLine(0x26d6, 3);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x26d6, "MOTHER", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -57,7 +48,7 @@ Common::Error MotherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMotherLine(0x26e9, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x26e9, "MOTHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -67,7 +58,7 @@ Common::Error MotherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMotherLine(0x26f5, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x26f5, "MOTHER", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -81,7 +72,7 @@ Common::Error MotherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMotherLine(0x2709, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2709, "MOTHER", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -89,11 +80,11 @@ Common::Error MotherDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMotherLine(0x2714, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2714, "MOTHER", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playMotherLine(0x2719, 3);
+ return runtime.playDialogueLineWithVariant(0x2719, "MOTHER", 3);
}
} // End of namespace Harvester
diff --git a/engines/harvester/npc/mother_dialogue.h b/engines/harvester/npc/mother_dialogue.h
index b52827e2b7b..31567739e43 100644
--- a/engines/harvester/npc/mother_dialogue.h
+++ b/engines/harvester/npc/mother_dialogue.h
@@ -32,7 +32,6 @@ public:
bool talkStatePending = true;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = MotherRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.talkStatePending);
diff --git a/engines/harvester/npc/moynahan_dialogue.cpp b/engines/harvester/npc/moynahan_dialogue.cpp
index e7c94b85c1b..0482531fb42 100644
--- a/engines/harvester/npc/moynahan_dialogue.cpp
+++ b/engines/harvester/npc/moynahan_dialogue.cpp
@@ -29,9 +29,6 @@ namespace Harvester {
namespace {
-static const char *const kMoynahanNpc = "MOYNAHAN";
-static const char *const kMoynahanEmbalmingPortrait = "MOYNAHAN_MBLM";
-static const char *const kPcSpeaker = "PC";
static const char *const kMoynahanHotelRoom = "HTL-RT";
static const char *const kMoynahanEmbalmingRoom = "MBLM";
static const char *const kRahRoom = "RAH";
@@ -48,185 +45,166 @@ static const int kMoynahanLateTopicLines[] = { 0x1b8, 0x1b9, 0x1ba, 0x1bb, 0x1bc
static const int kMoynahanGlueTopicLines[] = { 0x1bf, 0x1c0, 0x1c1, 0x1c2 };
static const DialogueLineEntry kMoynahanGlueInterruptOpeningLines[] = {
- { 0x3e4d, kMoynahanNpc, 2 },
- { 0x3e52, kPcSpeaker, 0 },
- { 0x3e56, kMoynahanNpc, 0 }
+ { 0x3e4d, "MOYNAHAN", 2 },
+ { 0x3e52, "PC", 0 },
+ { 0x3e56, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanGlueInterruptShortReplyLines[] = {
- { 0x3e76, kPcSpeaker, 0 },
- { 0x3e7a, kMoynahanNpc, 0 }
+ { 0x3e76, "PC", 0 },
+ { 0x3e7a, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanGlueInterruptExtendedReplyLines[] = {
- { 0x3e5b, kPcSpeaker, 0 },
- { 0x3e60, kMoynahanNpc, 0 },
- { 0x3e64, kPcSpeaker, 2 },
- { 0x3e69, kMoynahanNpc, 0 },
- { 0x3e6d, kPcSpeaker, 2 },
- { 0x3e71, kMoynahanNpc, 2 }
+ { 0x3e5b, "PC", 0 },
+ { 0x3e60, "MOYNAHAN", 0 },
+ { 0x3e64, "PC", 2 },
+ { 0x3e69, "MOYNAHAN", 0 },
+ { 0x3e6d, "PC", 2 },
+ { 0x3e71, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanIntroLines[] = {
- { 0x3d33, kMoynahanNpc, 0 },
- { 0x3d37, kPcSpeaker, 0 },
- { 0x3d3b, kMoynahanNpc, 0 },
- { 0x3d40, kPcSpeaker, 0 },
- { 0x3d45, kMoynahanNpc, 0 },
- { 0x3d47, kMoynahanNpc, 0 }
+ { 0x3d33, "MOYNAHAN", 0 },
+ { 0x3d37, "PC", 0 },
+ { 0x3d3b, "MOYNAHAN", 0 },
+ { 0x3d40, "PC", 0 },
+ { 0x3d45, "MOYNAHAN", 0 },
+ { 0x3d47, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanSlashMarksIntroLines[] = {
- { 0x3da0, kMoynahanNpc, 3 },
- { 0x3da1, kMoynahanNpc, 3 },
- { 0x3da2, kMoynahanNpc, 2 }
+ { 0x3da0, "MOYNAHAN", 3 },
+ { 0x3da1, "MOYNAHAN", 3 },
+ { 0x3da2, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanDayFiveLines[] = {
- { 0x3fe5, kMoynahanNpc, 1 },
- { 0x3fea, kPcSpeaker, 0 },
- { 0x3fee, kMoynahanNpc, 2 },
- { 0x3ff3, kPcSpeaker, 0 },
- { 0x3ff7, kMoynahanNpc, 0 }
+ { 0x3fe5, "MOYNAHAN", 1 },
+ { 0x3fea, "PC", 0 },
+ { 0x3fee, "MOYNAHAN", 2 },
+ { 0x3ff3, "PC", 0 },
+ { 0x3ff7, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanKarinKidnapedTailLines[] = {
- { 0x4020, kMoynahanNpc, 0 },
- { 0x4026, kPcSpeaker, 0 },
- { 0x402a, kMoynahanNpc, 0 },
- { 0x4034, kPcSpeaker, 0 },
- { 0x4038, kMoynahanNpc, 0 },
- { 0x403d, kPcSpeaker, 0 },
- { 0x4041, kMoynahanNpc, 1 }
+ { 0x4020, "MOYNAHAN", 0 },
+ { 0x4026, "PC", 0 },
+ { 0x402a, "MOYNAHAN", 0 },
+ { 0x4034, "PC", 0 },
+ { 0x4038, "MOYNAHAN", 0 },
+ { 0x403d, "PC", 0 },
+ { 0x4041, "MOYNAHAN", 1 }
};
static const DialogueLineEntry kMoynahanCasketIntroLines[] = {
- { 0x3e84, kMoynahanNpc, 0 },
- { 0x3e89, kPcSpeaker, 0 },
- { 0x3e8e, kMoynahanNpc, 0 },
- { 0x3e93, kPcSpeaker, 0 },
- { 0x3e98, kMoynahanNpc, 2 }
+ { 0x3e84, "MOYNAHAN", 0 },
+ { 0x3e89, "PC", 0 },
+ { 0x3e8e, "MOYNAHAN", 0 },
+ { 0x3e93, "PC", 0 },
+ { 0x3e98, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanCasketResponseOneLines[] = {
- { 0x3ea4, kMoynahanNpc, 0 },
- { 0x3ea8, kPcSpeaker, 2 },
- { 0x3ead, kMoynahanNpc, 2 }
+ { 0x3ea4, "MOYNAHAN", 0 },
+ { 0x3ea8, "PC", 2 },
+ { 0x3ead, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanCasketFollowupLines[] = {
- { 0x3eb7, kPcSpeaker, 2 },
- { 0x3ebc, kMoynahanNpc, 2 }
+ { 0x3eb7, "PC", 2 },
+ { 0x3ebc, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanLedgerIntroLines[] = {
- { 0x3ede, kPcSpeaker, 0 },
- { 0x3ee3, kMoynahanNpc, 0 },
- { 0x3ee7, kPcSpeaker, 0 },
- { 0x3eec, kMoynahanNpc, 0 }
+ { 0x3ede, "PC", 0 },
+ { 0x3ee3, "MOYNAHAN", 0 },
+ { 0x3ee7, "PC", 0 },
+ { 0x3eec, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanLedgerResponseOneLines[] = {
- { 0x3ef7, kMoynahanNpc, 0 },
- { 0x3efb, kPcSpeaker, 0 },
- { 0x3eff, kMoynahanNpc, 2 },
- { 0x3f05, kPcSpeaker, 2 }
+ { 0x3ef7, "MOYNAHAN", 0 },
+ { 0x3efb, "PC", 0 },
+ { 0x3eff, "MOYNAHAN", 2 },
+ { 0x3f05, "PC", 2 }
};
static const DialogueLineEntry kMoynahanLedgerResponseTwoLines[] = {
- { 0x3f09, kMoynahanNpc, 0 },
- { 0x3f0f, kPcSpeaker, 2 },
- { 0x3f13, kMoynahanNpc, 0 },
- { 0x3f18, kPcSpeaker, 2 }
+ { 0x3f09, "MOYNAHAN", 0 },
+ { 0x3f0f, "PC", 2 },
+ { 0x3f13, "MOYNAHAN", 0 },
+ { 0x3f18, "PC", 2 }
};
static const DialogueLineEntry kMoynahanMatchesLines[] = {
- { 0x4049, kPcSpeaker, 0 },
- { 0x404d, kMoynahanNpc, 0 }
+ { 0x4049, "PC", 0 },
+ { 0x404d, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanGoodCauseLines[] = {
- { 0x3d5f, kMoynahanNpc, 0 },
- { 0x3d66, kPcSpeaker, 0 },
- { 0x3d6a, kMoynahanNpc, 0 }
+ { 0x3d5f, "MOYNAHAN", 0 },
+ { 0x3d66, "PC", 0 },
+ { 0x3d6a, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanSlashMarksTopicReplyLines[] = {
- { 0x3d76, kMoynahanNpc, 0 },
- { 0x3d7d, kPcSpeaker, 0 },
- { 0x3d81, kMoynahanNpc, 0 },
- { 0x3d88, kPcSpeaker, 0 },
- { 0x3d8c, kMoynahanNpc, 0 },
- { 0x3d92, kPcSpeaker, 0 },
- { 0x3d96, kMoynahanNpc, 0 }
+ { 0x3d76, "MOYNAHAN", 0 },
+ { 0x3d7d, "PC", 0 },
+ { 0x3d81, "MOYNAHAN", 0 },
+ { 0x3d88, "PC", 0 },
+ { 0x3d8c, "MOYNAHAN", 0 },
+ { 0x3d92, "PC", 0 },
+ { 0x3d96, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanGeneralTopicResponseOneLines[] = {
- { 0x3dbe, kMoynahanNpc, 1 },
- { 0x3dc4, kPcSpeaker, 0 },
- { 0x3dc8, kMoynahanNpc, 2 }
+ { 0x3dbe, "MOYNAHAN", 1 },
+ { 0x3dc4, "PC", 0 },
+ { 0x3dc8, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanGeneralTopicResponseTwoLines[] = {
- { 0x3dcf, kMoynahanNpc, 0 },
- { 0x3dd4, kPcSpeaker, 0 },
- { 0x3dd8, kMoynahanNpc, 1 },
- { 0x3ddd, kPcSpeaker, 0 },
- { 0x3de2, kMoynahanNpc, 2 }
+ { 0x3dcf, "MOYNAHAN", 0 },
+ { 0x3dd4, "PC", 0 },
+ { 0x3dd8, "MOYNAHAN", 1 },
+ { 0x3ddd, "PC", 0 },
+ { 0x3de2, "MOYNAHAN", 2 }
};
static const DialogueLineEntry kMoynahanDayFiveUnlockLines[] = {
- { 0x3df5, kMoynahanNpc, 3 },
- { 0x3dfc, kPcSpeaker, 0 },
- { 0x3e00, kMoynahanNpc, 0 },
- { 0x3e05, kPcSpeaker, 0 },
- { 0x3e0a, kMoynahanNpc, 0 }
+ { 0x3df5, "MOYNAHAN", 3 },
+ { 0x3dfc, "PC", 0 },
+ { 0x3e00, "MOYNAHAN", 0 },
+ { 0x3e05, "PC", 0 },
+ { 0x3e0a, "MOYNAHAN", 0 }
};
static const DialogueLineEntry kMoynahanEmbalmingRoomLines[] = {
- { 0x3e18, kMoynahanNpc, 0 },
- { 0x3e22, kPcSpeaker, 0 },
- { 0x3e26, kMoynahanNpc, 2 }
+ { 0x3e18, "MOYNAHAN", 0 },
+ { 0x3e22, "PC", 0 },
+ { 0x3e26, "MOYNAHAN", 2 }
};
-static Common::Error playDialogueSequence(DialogueRuntime &runtime,
- const DialogueLineEntry *lines, uint count) {
- return runtime.playDialogueEntrySequence(lines, count);
-}
-
} // End of namespace
-bool MoynahanDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase(kMoynahanNpc) ||
- npcName.equalsIgnoreCase(kMoynahanEmbalmingPortrait);
-}
-
Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
MoynahanRoomDialogueState &state = _state;
Common::String topicBuffer;
int topicBufferLineIndex = -1;
- auto assignTopicBuffer = [&](int responseLineIndex) {
- runtime.assignTopicBuffer(topicBuffer, topicBufferLineIndex,
- responseLineIndex, "Moynahan topic buffer");
- };
+ DialogueTopicBuffer topics(runtime, topicBuffer, topicBufferLineIndex, "Moynahan topic buffer");
auto appendTopicBuffer = [&](int responseLineIndex) {
if (topicBuffer.empty()) {
- assignTopicBuffer(responseLineIndex);
+ topics.assign(responseLineIndex);
return;
}
topicBuffer += runtime.startupText().getDialogueResponseLine(responseLineIndex);
topicBufferLineIndex = -1;
};
- auto clearTopicBuffer = [&]() {
- topicBuffer.clear();
- topicBufferLineIndex = -1;
- };
- auto playMoynahanLine = [&](int wavId, int headVariant = 0) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, kMoynahanNpc, headVariant);
- };
+
auto queueRoomVisualMutation = [&](bool changed) {
if (!changed)
return;
@@ -260,32 +238,30 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
};
if (runtime.startupScript().getFlagValue("IF_TRY_TO_TAKE_THE_GLUE")) {
- Common::Error lineError = playDialogueSequence(runtime,
- kMoynahanGlueInterruptOpeningLines, ARRAYSIZE(kMoynahanGlueInterruptOpeningLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMoynahanGlueInterruptOpeningLines,
+ ARRAYSIZE(kMoynahanGlueInterruptOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (!runtime.startupScript().getFlagValue("IF_SAW_THE_SLASHES_ON_THE_BODY") ||
!state.slashMarksTopicUnlocked) {
- return playDialogueSequence(runtime,
- kMoynahanGlueInterruptShortReplyLines,
+ return runtime.playDialogueEntrySequence(kMoynahanGlueInterruptShortReplyLines,
ARRAYSIZE(kMoynahanGlueInterruptShortReplyLines));
}
- return playDialogueSequence(runtime,
- kMoynahanGlueInterruptExtendedReplyLines,
+ return runtime.playDialogueEntrySequence(kMoynahanGlueInterruptExtendedReplyLines,
ARRAYSIZE(kMoynahanGlueInterruptExtendedReplyLines));
}
if (!usedItemName.empty()) {
if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
- return playMoynahanLine(0x3e45);
+ return runtime.playDialogueLineWithVariant(0x3e45, "MOYNAHAN", 0);
}
if (isCasketPhoto(usedItemName)) {
- Common::Error lineError = playDialogueSequence(runtime,
- kMoynahanCasketIntroLines, ARRAYSIZE(kMoynahanCasketIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMoynahanCasketIntroLines,
+ ARRAYSIZE(kMoynahanCasketIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -295,23 +271,22 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playDialogueSequence(runtime, kMoynahanCasketResponseOneLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanCasketResponseOneLines,
ARRAYSIZE(kMoynahanCasketResponseOneLines));
} else if (responseIndex == 2) {
- lineError = playMoynahanLine(0x3eb1, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3eb1, "MOYNAHAN", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDialogueSequence(runtime, kMoynahanCasketFollowupLines,
- ARRAYSIZE(kMoynahanCasketFollowupLines));
+ lineError = runtime.playDialogueEntrySequence(kMoynahanCasketFollowupLines, ARRAYSIZE(kMoynahanCasketFollowupLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (state.gotGlue)
- return playMoynahanLine(0x3ec3, 2);
+ return runtime.playDialogueLineWithVariant(0x3ec3, "MOYNAHAN", 2);
- lineError = playMoynahanLine(0x3ec8, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3ec8, "MOYNAHAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -321,7 +296,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMoynahanLine(0x3ed2, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3ed2, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -333,7 +308,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (responseIndex == 2)
- return playMoynahanLine(0x3ed7, 1);
+ return runtime.playDialogueLineWithVariant(0x3ed7, "MOYNAHAN", 1);
return Common::kNoError;
}
@@ -342,20 +317,20 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
runtime.startupScript().getFlagValue("HAVE_BOTH_LEDGERS")) {
if (sharedState.discussedLedgerEvidence != 0 && !state.ledgerEvidenceLinePlayed) {
state.ledgerEvidenceLinePlayed = true;
- Common::Error lineError = playMoynahanLine(0x3f87, 2);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3f87, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
runtime.setActiveSpeakerPortrait(
runtime.currentRoomName().equalsIgnoreCase(kMoynahanHotelRoom)
- ? kMoynahanNpc
- : kMoynahanEmbalmingPortrait,
+ ? "MOYNAHAN"
+ : "MOYNAHAN_MBLM",
0);
return Common::kNoError;
}
- Common::Error lineError = playDialogueSequence(runtime,
- kMoynahanLedgerIntroLines, ARRAYSIZE(kMoynahanLedgerIntroLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMoynahanLedgerIntroLines,
+ ARRAYSIZE(kMoynahanLedgerIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -365,24 +340,22 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playDialogueSequence(runtime,
- kMoynahanLedgerResponseOneLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanLedgerResponseOneLines,
ARRAYSIZE(kMoynahanLedgerResponseOneLines));
} else if (responseIndex == 2) {
- lineError = playDialogueSequence(runtime,
- kMoynahanLedgerResponseTwoLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanLedgerResponseTwoLines,
ARRAYSIZE(kMoynahanLedgerResponseTwoLines));
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playMoynahanLine(0x3ed7, 1);
+ return runtime.playDialogueLineWithVariant(0x3ed7, "MOYNAHAN", 1);
}
if (isBlackmailEvidence(usedItemName)) {
sharedState.discussedNoteCheckbookEvidence = 1;
- Common::Error lineError = playMoynahanLine(0x3f3e);
+ Common::Error lineError = runtime.playDialogueLineWithVariant(0x3f3e, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -392,54 +365,53 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMoynahanLine(0x3f4a);
+ lineError = runtime.playDialogueLineWithVariant(0x3f4a, "MOYNAHAN", 0);
} else if (responseIndex == 2) {
- lineError = playMoynahanLine(0x3f4f, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3f4f, "MOYNAHAN", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- return playMoynahanLine(0x3f54, 2);
+ return runtime.playDialogueLineWithVariant(0x3f54, "MOYNAHAN", 2);
}
if (usedItemName.equalsIgnoreCase("WED_MATCHES")) {
- Common::Error lineError = playDialogueSequence(runtime,
- kMoynahanMatchesLines, ARRAYSIZE(kMoynahanMatchesLines));
+ Common::Error lineError = runtime.playDialogueEntrySequence(kMoynahanMatchesLines, ARRAYSIZE(kMoynahanMatchesLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED"))
- return playMoynahanLine(0x4054, 3);
+ return runtime.playDialogueLineWithVariant(0x4054, "MOYNAHAN", 3);
return Common::kNoError;
}
- return playMoynahanLine(0x3e3f, 2);
+ return runtime.playDialogueLineWithVariant(0x3e3f, "MOYNAHAN", 2);
}
Common::Error lineError;
if (state.introPending) {
state.introPending = false;
- lineError = playDialogueSequence(runtime, kMoynahanIntroLines, ARRAYSIZE(kMoynahanIntroLines));
+ lineError = runtime.playDialogueEntrySequence(kMoynahanIntroLines, ARRAYSIZE(kMoynahanIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
const DialogueLineEntry tailLines[] = {
- { 0x3d50, kPcSpeaker, 0 },
- { 0x3d54, kMoynahanNpc, 0 }
+ { 0x3d50, "PC", 0 },
+ { 0x3d54, "MOYNAHAN", 0 }
};
- lineError = playDialogueSequence(runtime, tailLines, ARRAYSIZE(tailLines));
+ lineError = runtime.playDialogueEntrySequence(tailLines, ARRAYSIZE(tailLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignTopicBuffer(runtime.currentRoomName().equalsIgnoreCase(kMoynahanEmbalmingRoom) ? 0x193 : 0x192);
+ topics.assign(runtime.currentRoomName().equalsIgnoreCase(kMoynahanEmbalmingRoom) ? 0x193 : 0x192);
} else {
- lineError = playMoynahanLine(0x3fd1);
+ lineError = runtime.playDialogueLineWithVariant(0x3fd1, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("IF_SAW_THE_SLASHES_ON_THE_BODY") &&
!state.slashMarksIntroShown) {
- lineError = playDialogueSequence(runtime, kMoynahanSlashMarksIntroLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanSlashMarksIntroLines,
ARRAYSIZE(kMoynahanSlashMarksIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -448,21 +420,21 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.slashMarksTopicUnlocked = true;
state.slashMarksIntroShown = true;
if (topicBuffer.empty())
- assignTopicBuffer(0x194);
+ topics.assign(0x194);
else
appendTopicBuffer(0x195);
}
if (sharedState.discussedCasketPhotoEvidence != 0 && !state.introPending) {
state.introPending = true;
- lineError = playMoynahanLine(0x3f5b, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3f5b, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("HAVE_BOTH_LEDGERS") && !state.ledgersIntroduced) {
state.ledgersIntroduced = true;
- lineError = playMoynahanLine(0x3f65);
+ lineError = runtime.playDialogueLineWithVariant(0x3f65, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -472,25 +444,25 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMoynahanLine(0x3f70);
+ lineError = runtime.playDialogueLineWithVariant(0x3f70, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)runtime.startupScript().resetRuntimeObjectToInitialState("LEDGER");
(void)runtime.startupScript().resetRuntimeObjectToInitialState("LEDGER2");
} else if (responseIndex == 2) {
- lineError = playMoynahanLine(0x3f76);
+ lineError = runtime.playDialogueLineWithVariant(0x3f76, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getCurrentStoryDayIndex() > 2) {
sharedState.moynahanKarinKidnapedDiscussionState = true;
- lineError = playMoynahanLine(0x3f7a);
+ lineError = runtime.playDialogueLineWithVariant(0x3f7a, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playMoynahanLine(0x3f7e, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3f7e, "MOYNAHAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -499,15 +471,14 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED") &&
!state.stephMidgameShown) {
state.stephMidgameShown = true;
- lineError = playMoynahanLine(0x3fd9);
+ lineError = runtime.playDialogueLineWithVariant(0x3fd9, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getCurrentStoryDayIndex() == 5 && !state.dayFiveShown) {
state.dayFiveShown = true;
- lineError = playDialogueSequence(runtime, kMoynahanDayFiveLines,
- ARRAYSIZE(kMoynahanDayFiveLines));
+ lineError = runtime.playDialogueEntrySequence(kMoynahanDayFiveLines, ARRAYSIZE(kMoynahanDayFiveLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -515,7 +486,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("BURNED_TV_STATION") &&
!state.burnedTvStationShown) {
state.burnedTvStationShown = true;
- lineError = playMoynahanLine(0x3ffe);
+ lineError = runtime.playDialogueLineWithVariant(0x3ffe, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -523,7 +494,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("KARIN_KIDNAPED") &&
!state.karinKidnapedShown) {
state.karinKidnapedShown = true;
- lineError = playMoynahanLine(0x4007);
+ lineError = runtime.playDialogueLineWithVariant(0x4007, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -533,18 +504,18 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMoynahanLine(0x4012);
+ lineError = runtime.playDialogueLineWithVariant(0x4012, "MOYNAHAN", 0);
} else if (responseIndex == 2) {
const DialogueLineEntry responseTwoLines[] = {
- { 0x4017, kMoynahanNpc, 0 },
- { 0x401c, kPcSpeaker, 0 }
+ { 0x4017, "MOYNAHAN", 0 },
+ { 0x401c, "PC", 0 }
};
- lineError = playDialogueSequence(runtime, responseTwoLines, ARRAYSIZE(responseTwoLines));
+ lineError = runtime.playDialogueEntrySequence(responseTwoLines, ARRAYSIZE(responseTwoLines));
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playDialogueSequence(runtime, kMoynahanKarinKidnapedTailLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanKarinKidnapedTailLines,
ARRAYSIZE(kMoynahanKarinKidnapedTailLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -556,7 +527,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!runtime.startupScript().isNamedNpcDeathTypeClear("BUTCHER") &&
!state.butcherDeadShown) {
state.butcherDeadShown = true;
- lineError = playMoynahanLine(0x40bb, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x40bb, "MOYNAHAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -564,7 +535,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!runtime.startupScript().isNamedNpcDeathTypeClear("JIMMY") &&
!state.jimmyDeadShown) {
state.jimmyDeadShown = true;
- lineError = playMoynahanLine(0x40cd, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x40cd, "MOYNAHAN", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -572,7 +543,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("KARIN_FOUND_DEAD") &&
!state.karinFoundDeadShown) {
state.karinFoundDeadShown = true;
- lineError = playMoynahanLine(0x40d4, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x40d4, "MOYNAHAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -588,37 +559,36 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (selectedTopic.equalsIgnoreCase(runtime.genericByeTopic()) ||
runtime.matchesResponseLine(selectedTopic, 0x199))
- return playMoynahanLine(0x3e32, 3);
+ return runtime.playDialogueLineWithVariant(0x3e32, "MOYNAHAN", 3);
if (runtime.matchesAnyResponseLine(selectedTopic, kMoynahanGoodCauseTopicLines,
ARRAYSIZE(kMoynahanGoodCauseTopicLines))) {
sharedState.momGoodCauseDay5State = true;
- lineError = playDialogueSequence(runtime, kMoynahanGoodCauseLines,
- ARRAYSIZE(kMoynahanGoodCauseLines));
+ lineError = runtime.playDialogueEntrySequence(kMoynahanGoodCauseLines, ARRAYSIZE(kMoynahanGoodCauseLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignTopicBuffer(0x19c);
+ topics.assign(0x19c);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMoynahanSlashMarksTopicLines,
ARRAYSIZE(kMoynahanSlashMarksTopicLines))) {
- lineError = playDialogueSequence(runtime, kMoynahanSlashMarksTopicReplyLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanSlashMarksTopicReplyLines,
ARRAYSIZE(kMoynahanSlashMarksTopicReplyLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignTopicBuffer(0x1a1);
+ topics.assign(0x1a1);
continue;
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMoynahanBodyTopicLines,
ARRAYSIZE(kMoynahanBodyTopicLines))) {
- lineError = playMoynahanLine(0x3da0, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3da0, "MOYNAHAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getCurrentStoryDayIndex() > 4) {
- lineError = playMoynahanLine(0x3da1, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x3da1, "MOYNAHAN", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -626,11 +596,11 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.slashMarksTopicUnlocked = true;
}
- lineError = playMoynahanLine(0x3da2, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x3da2, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignTopicBuffer(0x1a6);
+ topics.assign(0x1a6);
if (runtime.startupScript().getCurrentStoryDayIndex() > 4)
appendTopicBuffer(0x1a7);
if (runtime.currentRoomName().equalsIgnoreCase(kMoynahanEmbalmingRoom))
@@ -640,7 +610,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kMoynahanGeneralTopicLines,
ARRAYSIZE(kMoynahanGeneralTopicLines))) {
- lineError = playMoynahanLine(0x3db1);
+ lineError = runtime.playDialogueLineWithVariant(0x3db1, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -650,27 +620,25 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playDialogueSequence(runtime,
- kMoynahanGeneralTopicResponseOneLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanGeneralTopicResponseOneLines,
ARRAYSIZE(kMoynahanGeneralTopicResponseOneLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignTopicBuffer(0x1ad);
+ topics.assign(0x1ad);
} else if (responseIndex == 2) {
- lineError = playDialogueSequence(runtime,
- kMoynahanGeneralTopicResponseTwoLines,
+ lineError = runtime.playDialogueEntrySequence(kMoynahanGeneralTopicResponseTwoLines,
ARRAYSIZE(kMoynahanGeneralTopicResponseTwoLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getCurrentStoryDayIndex() > 4) {
- lineError = playMoynahanLine(0x3deb);
+ lineError = runtime.playDialogueLineWithVariant(0x3deb, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2ec8 = true;
}
- assignTopicBuffer(0x1b0);
+ topics.assign(0x1b0);
if (runtime.startupScript().getCurrentStoryDayIndex() > 4)
appendTopicBuffer(0x1b1);
}
@@ -683,13 +651,12 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.dialogueStateD2ec8 = true;
sharedState.dialogueStateD2ebc = true;
sharedState.dialogueStateD2ec0 = true;
- lineError = playDialogueSequence(runtime, kMoynahanDayFiveUnlockLines,
- ARRAYSIZE(kMoynahanDayFiveUnlockLines));
+ lineError = runtime.playDialogueEntrySequence(kMoynahanDayFiveUnlockLines, ARRAYSIZE(kMoynahanDayFiveUnlockLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
state.slashMarksTopicUnlocked = true;
- clearTopicBuffer();
+ topics.clear();
}
continue;
}
@@ -697,11 +664,10 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kMoynahanEmbalmingRoomTopicLines,
ARRAYSIZE(kMoynahanEmbalmingRoomTopicLines))) {
if (runtime.currentRoomName().equalsIgnoreCase(kMoynahanEmbalmingRoom)) {
- lineError = playDialogueSequence(runtime, kMoynahanEmbalmingRoomLines,
- ARRAYSIZE(kMoynahanEmbalmingRoomLines));
+ lineError = runtime.playDialogueEntrySequence(kMoynahanEmbalmingRoomLines, ARRAYSIZE(kMoynahanEmbalmingRoomLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
- assignTopicBuffer(0x1b6);
+ topics.assign(0x1b6);
}
continue;
}
@@ -709,7 +675,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kMoynahanLateTopicLines,
ARRAYSIZE(kMoynahanLateTopicLines))) {
if (runtime.startupScript().getCurrentStoryDayIndex() > 4) {
- lineError = playMoynahanLine(0x40f5);
+ lineError = runtime.playDialogueLineWithVariant(0x40f5, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -720,7 +686,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
ARRAYSIZE(kMoynahanGlueTopicLines))) {
if (runtime.startupScript().getCurrentStoryDayIndex() > 4) {
if (!state.gotGlue) {
- lineError = playMoynahanLine(0x40fb);
+ lineError = runtime.playDialogueLineWithVariant(0x40fb, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -730,17 +696,17 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMoynahanLine(0x4108, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x4108, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
queueRoomVisualMutation(giveGlue());
} else if (responseIndex == 2) {
- lineError = playMoynahanLine(0x410d, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x410d, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else {
- lineError = playMoynahanLine(0x410d, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x410d, "MOYNAHAN", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -751,7 +717,7 @@ Common::Error MoynahanDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0x1c4))
continue;
- lineError = playMoynahanLine(0x3e39);
+ lineError = runtime.playDialogueLineWithVariant(0x3e39, "MOYNAHAN", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/moynahan_dialogue.h b/engines/harvester/npc/moynahan_dialogue.h
index f72ca8e1116..abe46548bbd 100644
--- a/engines/harvester/npc/moynahan_dialogue.h
+++ b/engines/harvester/npc/moynahan_dialogue.h
@@ -44,7 +44,6 @@ public:
bool karinFoundDeadShown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override { _state = MoynahanRoomDialogueState(); }
void syncState(Common::Serializer &s) override {
syncDialogueBool(s, _state.introPending);
diff --git a/engines/harvester/npc/mr_potts_dialogue.cpp b/engines/harvester/npc/mr_potts_dialogue.cpp
index f1190d9290e..7f00aa25b5c 100644
--- a/engines/harvester/npc/mr_potts_dialogue.cpp
+++ b/engines/harvester/npc/mr_potts_dialogue.cpp
@@ -260,13 +260,6 @@ static const int kMrPottsPeepholeTopicResponseLines[] = {
} // End of namespace
-bool MrPottsDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("MR_POTTS") ||
- npcName.equalsIgnoreCase("POTTS_FLESH") ||
- npcName.equalsIgnoreCase("MR_POTTS_CEM10") ||
- npcName.equalsIgnoreCase("MR_POTTS_HALL");
-}
-
Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const Common::String &usedItemName, DialogueSharedState &sharedState) {
MrPottsRoomDialogueState &state = _state;
@@ -279,32 +272,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
responseLineIndex, "Mr Potts topic buffer");
state.topicBufferLineIndex = mrPottsTopicBufferLineIndex;
};
- auto playMrPottsLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, "MR_POTTS", headVariant);
- };
- auto playMrsPottsLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, "MRS_POTTS", headVariant);
- };
- auto playPcLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, "PC", headVariant);
- };
- auto playPottsFleshLine = [&](int wavId, int headVariant) -> Common::Error {
- return runtime.playDialogueLineWithVariant(wavId, "POTTS_FLESH", headVariant);
- };
- auto playSequence = [&](const DialogueLineEntry *lines, uint count) -> Common::Error {
- return runtime.playDialogueEntrySequence(lines, count);
- };
+
auto hasInventoryItem = [&](const char *objectName) {
return runtime.startupScript().isObjectInInventory(objectName);
};
- auto executeActionTagIfSet = [&](const char *tag) {
- InteractionResult interaction;
- if (!runtime.executeActionTag(tag, interaction))
- return;
- runtime.applyImmediateDialogueInteractionEffects(interaction);
- runtime.queueDialogueInteractionIfNeeded(interaction);
- };
auto queueNpcDeathOrMonsterfyTransition = [&](const char *npcName) {
InteractionResult interaction;
if (runtime.startupScript().finalizeRuntimeNpcDeathOrMonsterfy(npcName))
@@ -326,7 +298,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (hasInventoryItem("HARVEST_BLADE")) {
(void)runtime.startupScript().setRuntimeFlagValue("PC_TALKED_TO_POTTS", true);
- lineError = playSequence(kMrPottsHarvestBladeOpeningLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsHarvestBladeOpeningLines,
ARRAYSIZE(kMrPottsHarvestBladeOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -337,28 +309,28 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playPottsFleshLine(0x2f3d, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x2f3d, "POTTS_FLESH", 4);
} else if (responseIndex == 2) {
- lineError = playPottsFleshLine(0x2f42, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2f42, "POTTS_FLESH", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPottsFleshLine(0x2f46, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2f46, "POTTS_FLESH", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPottsFleshLine(0x2f4d, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x2f4d, "POTTS_FLESH", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet(kMonsterfyPottsActionTag);
+ runtime.executeAndQueueAction(kMonsterfyPottsActionTag);
return Common::kNoError;
}
if (runtime.startupScript().getFlagValue("STEPHANIE_DEAD_IN_HALL_JUST_OUTSIDE")) {
(void)runtime.startupScript().setRuntimeFlagValue(
"STEPHANIE_DEAD_IN_HALL_JUST_OUTSIDE", false);
- lineError = playSequence(kMrPottsStephanieDeadInHallLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsStephanieDeadInHallLines,
ARRAYSIZE(kMrPottsStephanieDeadInHallLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -370,7 +342,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (lineError.getCode() != Common::kNoError)
return lineError;
- executeActionTagIfSet(kStephHallExitActionTag);
+ runtime.executeAndQueueAction(kStephHallExitActionTag);
return Common::kNoError;
}
@@ -380,21 +352,21 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
lineError = runtime.playDialogueFst(kDialogueC016AFstPath);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(kMrPottsPottsdamDiggingIntroLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsPottsdamDiggingIntroLines,
ARRAYSIZE(kMrPottsPottsdamDiggingIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
return Common::kNoError;
}
- lineError = playMrPottsLine(0x2cd9, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2cd9, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
return Common::kNoError;
}
if (runtime.startupScript().getFlagValue("POTTSDAM_DIGGING_KARIN")) {
- lineError = playSequence(kMrPottsPottsdamDiggingKarinLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsPottsdamDiggingKarinLines,
ARRAYSIZE(kMrPottsPottsdamDiggingKarinLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -405,7 +377,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!usedItemName.empty()) {
if (usedItemName.equalsIgnoreCase("MEAT")) {
- lineError = playMrPottsLine(0x2c7f, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2c7f, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -415,12 +387,12 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2c8a, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2c8a, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
(void)runtime.startupScript().resetRuntimeObjectToInitialState(kMeatObjectName);
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2c8f, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2c8f, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -429,19 +401,19 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
usedItemName.equalsIgnoreCase("CASKET_PHOTOCOPY")) {
sharedState.discussedCasketPhotoEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(DialogueFlags::kShownPhotoOfCorpse, true);
- lineError = playSequence(kMrPottsCasketPhotoLines, ARRAYSIZE(kMrPottsCasketPhotoLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsCasketPhotoLines, ARRAYSIZE(kMrPottsCasketPhotoLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
if (sharedState.dialogueStateD2ebc) {
- lineError = playSequence(
- kMrPottsCasketPhotoFollowupLines, ARRAYSIZE(kMrPottsCasketPhotoFollowupLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsCasketPhotoFollowupLines,
+ ARRAYSIZE(kMrPottsCasketPhotoFollowupLines));
}
} else if (usedItemName.equalsIgnoreCase("PHOTO_OF_WHALEY_HERRILL")) {
sharedState.discussedWhaleyHerrillPhoto = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownPhotoOfWhaleyHerrill, true);
- lineError = playSequence(
- kMrPottsWhaleyHerrillPhotoLines, ARRAYSIZE(kMrPottsWhaleyHerrillPhotoLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsWhaleyHerrillPhotoLines,
+ ARRAYSIZE(kMrPottsWhaleyHerrillPhotoLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -451,15 +423,15 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2cca, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2cca, "MR_POTTS", 0);
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2ccf, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2ccf, "MR_POTTS", 0);
} else if (responseIndex == 3) {
- lineError = playMrPottsLine(0x2cd4, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2cd4, "MR_POTTS", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMrPottsLine(0x2cd9, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2cd9, "MR_POTTS", 0);
} else if (usedItemName.equalsIgnoreCase("NOTE") ||
usedItemName.equalsIgnoreCase("NOTE_PHOTOCOPY") ||
usedItemName.equalsIgnoreCase("CHECKBOOK") ||
@@ -467,17 +439,16 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
sharedState.discussedNoteCheckbookEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownEvidenceOfBlackmail, true);
- lineError = playSequence(
- kMrPottsBlackmailEvidenceLines, ARRAYSIZE(kMrPottsBlackmailEvidenceLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsBlackmailEvidenceLines,
+ ARRAYSIZE(kMrPottsBlackmailEvidenceLines));
} else if (usedItemName.equalsIgnoreCase("TV_DEED") ||
usedItemName.equalsIgnoreCase("TV_DEED_PHOTOCOPY")) {
sharedState.discussedTvDeedEvidence = 1;
(void)runtime.startupScript().setRuntimeFlagValue(
DialogueFlags::kShownEvidenceSheriffOwns, true);
- lineError = playSequence(
- kMrPottsTvDeedEvidenceLines, ARRAYSIZE(kMrPottsTvDeedEvidenceLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsTvDeedEvidenceLines, ARRAYSIZE(kMrPottsTvDeedEvidenceLines));
} else {
- lineError = playMrPottsLine(0x2c79, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2c79, "MR_POTTS", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -485,7 +456,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.startupScript().getFlagValue("IF_TRY_TO_SEE_STEPHANIE")) {
- lineError = playMrPottsLine(0x2b18, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2b18, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
return Common::kNoError;
@@ -495,7 +466,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
state.auxIntroPending = false;
state.followupDayIndex = currentStoryDayIndex;
- lineError = playMrPottsLine(0x2988, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2988, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -505,26 +476,26 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(kMrPottsAuxIntroResponse1Lines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsAuxIntroResponse1Lines,
ARRAYSIZE(kMrPottsAuxIntroResponse1Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.dialogueStateD2f04 = true;
if (sharedState.dialogueStateD2ef4) {
- lineError = playSequence(kMrPottsAuxIntroResponse1WithMomIntroLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsAuxIntroResponse1WithMomIntroLines,
ARRAYSIZE(kMrPottsAuxIntroResponse1WithMomIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playMrPottsLine(0x29b0, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x29b0, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(
runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD") ? 0x1d9 : 0x1d8);
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x29ba, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x29ba, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(
@@ -532,12 +503,12 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
} else if (currentStoryDayIndex == state.followupDayIndex) {
lineError = stephanieIsDead
- ? playMrPottsLine(0x2aed, 3)
- : playMrPottsLine(0x2ac7, 1);
+ ? runtime.playDialogueLineWithVariant(0x2aed, "MR_POTTS", 3)
+ : runtime.playDialogueLineWithVariant(0x2ac7, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (!stephanieIsDead) {
- lineError = playMrPottsLine(0x2ace, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2ace, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -547,11 +518,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2ad8, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2ad8, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2adc, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x2adc, "MR_POTTS", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -562,13 +533,13 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
runtime.startupScript().getFlagValue("DAY_5")) &&
!state.stephanieAliveLaterDayShown) {
state.stephanieAliveLaterDayShown = true;
- lineError = playMrPottsLine(0x2ae5, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2ae5, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
state.followupDayIndex = runtime.startupScript().getCurrentStoryDayIndex();
} else {
- lineError = playMrPottsLine(0x2bdf, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2bdf, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -576,7 +547,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("KARIN_KIDNAPED") && !state.karinKidnapedShown) {
state.karinKidnapedShown = true;
- lineError = playMrPottsLine(0x2b1f, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2b1f, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -586,7 +557,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(kMrPottsKarinKidnapedResponse1Lines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsKarinKidnapedResponse1Lines,
ARRAYSIZE(kMrPottsKarinKidnapedResponse1Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -597,11 +568,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (nestedResponseIndex == 1) {
- lineError = playMrPottsLine(0x2b45, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2b45, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (nestedResponseIndex == 2) {
- lineError = playMrPottsLine(0x2b4b, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2b4b, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -610,15 +581,15 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (responseError.getCode() != Common::kNoError)
return responseError;
- lineError = playSequence(kMrPottsKarinKidnapedResponse1NestedResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsKarinKidnapedResponse1NestedResponse2Lines,
ARRAYSIZE(kMrPottsKarinKidnapedResponse1NestedResponse2Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
}
} else if (responseIndex == 2) {
lineError = runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED")
- ? playMrPottsLine(0x2b79, 3)
- : playMrPottsLine(0x2b65, 0);
+ ? runtime.playDialogueLineWithVariant(0x2b79, "MR_POTTS", 3)
+ : runtime.playDialogueLineWithVariant(0x2b65, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -628,22 +599,22 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
runtime.startupScript().getFlagValue("KARIN_FOUND_DEAD") &&
!state.karinFoundDeadShown) {
state.karinFoundDeadShown = true;
- lineError = playMrPottsLine(0x2b82, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2b82, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("KARIN_FOUND_DEAD") && !state.karinFoundAliveShown) {
state.karinFoundAliveShown = true;
- lineError = playSequence(kMrPottsKarinFoundDeadIntroLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsKarinFoundDeadIntroLines,
ARRAYSIZE(kMrPottsKarinFoundDeadIntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.startupScript().getFlagValue("STEPH_MIDGAME_PLAYED")
- ? playSequence(kMrPottsKarinFoundDeadWithStephMidgameLines,
+ ? runtime.playDialogueEntrySequence(kMrPottsKarinFoundDeadWithStephMidgameLines,
ARRAYSIZE(kMrPottsKarinFoundDeadWithStephMidgameLines))
- : playSequence(kMrPottsKarinFoundDeadWithoutStephMidgameLines,
+ : runtime.playDialogueEntrySequence(kMrPottsKarinFoundDeadWithoutStephMidgameLines,
ARRAYSIZE(kMrPottsKarinFoundDeadWithoutStephMidgameLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -654,11 +625,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2bb2, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2bb2, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2bb6, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2bb6, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -670,7 +641,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.day6KarinShown) {
state.day6KarinShown = true;
- lineError = playMrPottsLine(0x2bbd, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2bbd, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -680,11 +651,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2bc8, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2bc8, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2bd1, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2bd1, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -698,12 +669,12 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (followupResponseIndex == 1) {
- lineError = playMrPottsLine(0x2be9, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2be9, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.discussedMrPottsTuesdayNightAlibi = true;
- lineError = playSequence(kMrPottsDay6KarinFoundAliveAlibiFollowupLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsDay6KarinFoundAliveAlibiFollowupLines,
ARRAYSIZE(kMrPottsDay6KarinFoundAliveAlibiFollowupLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -719,16 +690,16 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (nestedResponseIndex == 1) {
lineError = discussedMoynahanKarinKidnaped
- ? playMrPottsLine(0x2c15, 2)
- : playSequence(kMrPottsDay6KarinFoundAliveNoMoynahanLines,
+ ? runtime.playDialogueLineWithVariant(0x2c15, "MR_POTTS", 2)
+ : runtime.playDialogueEntrySequence(kMrPottsDay6KarinFoundAliveNoMoynahanLines,
ARRAYSIZE(kMrPottsDay6KarinFoundAliveNoMoynahanLines));
} else if (nestedResponseIndex == 2) {
- lineError = playMrsPottsLine(0x2c24, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2c24, "MRS_POTTS", 2);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (followupResponseIndex == 2) {
- lineError = playMrPottsLine(0x2c2c, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2c2c, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -738,34 +709,34 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.startupScript().getFlagValue("SCRATCHED_TUCKER") && !state.scratchedTuckerShown) {
state.scratchedTuckerShown = true;
- lineError = playMrPottsLine(0x2e54, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2e54, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("BARBER_POLE_STOLEN") && !state.barberPoleStolenShown) {
state.barberPoleStolenShown = true;
- lineError = playMrPottsLine(0x2e61, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2e61, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("BOLT_OF_CLOTH_TAKEN") && !state.boltOfClothTakenShown) {
state.boltOfClothTakenShown = true;
- lineError = playMrPottsLine(0x2e69, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2e69, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("DINER_BURNED") && !state.dinerBurnedShown) {
state.dinerBurnedShown = true;
- lineError = playMrPottsLine(0x2e72, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2e72, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.startupScript().getFlagValue("KARIN_KIDNAPED")
- ? playMrPottsLine(0x2e77, 0)
- : playMrPottsLine(0x2e7c, 3);
+ ? runtime.playDialogueLineWithVariant(0x2e77, "MR_POTTS", 0)
+ : runtime.playDialogueLineWithVariant(0x2e7c, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -774,7 +745,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
!state.gotRemainsForLodgeShown) {
state.gotRemainsForLodgeShown = true;
- lineError = playMrPottsLine(0x2e82, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2e82, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -784,49 +755,49 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2e8d, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2e8d, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2e91, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2e91, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playMrPottsLine(0x2e95, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2e95, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("PC_ESCAPED_JAIL") && !state.escapedJailShown) {
state.escapedJailShown = true;
- lineError = playMrPottsLine(0x2e9c, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2e9c, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (!runtime.startupScript().isNamedNpcDeathTypeClear("BUTCHER") && !state.butcherDeathShown) {
state.butcherDeathShown = true;
- lineError = playMrPottsLine(0x2ef2, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2ef2, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (!runtime.startupScript().isNamedNpcDeathTypeClear("MOYNAHAN") && !state.moynahanDeathShown) {
state.moynahanDeathShown = true;
- lineError = playMrPottsLine(0x2f08, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2f08, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
if (runtime.startupScript().getFlagValue("EDNA_HUNG") && !state.ednaHungShown) {
state.ednaHungShown = true;
- lineError = playMrPottsLine(0x2f0f, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2f0f, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
if (runtime.startupScript().getFlagValue("KARIN_HUNG")) {
- lineError = playMrPottsLine(0x2f14, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2f14, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -846,7 +817,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0x1ea)) {
if (!runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
- lineError = playSequence(kMrPottsAmnesiaTopicLines, ARRAYSIZE(kMrPottsAmnesiaTopicLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsAmnesiaTopicLines, ARRAYSIZE(kMrPottsAmnesiaTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x1eb);
@@ -855,7 +826,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, 0x1ec)) {
if (!runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
- lineError = playSequence(kMrPottsMarriageTopicLines, ARRAYSIZE(kMrPottsMarriageTopicLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsMarriageTopicLines, ARRAYSIZE(kMrPottsMarriageTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x1ed);
@@ -864,8 +835,8 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, 0x1ee)) {
if (!runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
- lineError = playSequence(
- kMrPottsCommitmentTopicLines, ARRAYSIZE(kMrPottsCommitmentTopicLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsCommitmentTopicLines,
+ ARRAYSIZE(kMrPottsCommitmentTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x1ef);
@@ -874,15 +845,15 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, 0x1f0)) {
if (sharedState.dialogueStateD2ed0) {
- lineError = playMrPottsLine(0x2a0d, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a0d, "MR_POTTS", 0);
} else if (runtime.startupScript().getFlagValue("HEARD_DAD_MOAN")) {
- lineError = playMrPottsLine(0x2a09, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a09, "MR_POTTS", 0);
} else {
- lineError = playMrPottsLine(0x2a08, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a08, "MR_POTTS", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(kMrPottsFatherTopicLines, ARRAYSIZE(kMrPottsFatherTopicLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsFatherTopicLines, ARRAYSIZE(kMrPottsFatherTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(
@@ -890,7 +861,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x1f3)) {
- lineError = playMrPottsLine(0x2a31, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2a31, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -900,13 +871,13 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2a3c, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2a3c, "MR_POTTS", 2);
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2a42, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2a42, "MR_POTTS", 1);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playSequence(kMrPottsSlaughterhouseTopicClosingLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsSlaughterhouseTopicClosingLines,
ARRAYSIZE(kMrPottsSlaughterhouseTopicClosingLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -916,7 +887,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesResponseLine(selectedTopic, 0x1f7)) {
if (!runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
- lineError = playMrPottsLine(0x2a5e, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a5e, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x1f8);
@@ -931,16 +902,16 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2a73, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a73, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2a7c, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a7c, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playMrPottsLine(0x2a81, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2a81, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x1fb);
@@ -950,7 +921,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesResponseLine(selectedTopic, 0x1fd)) {
if (!runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
sharedState.discussedLodgeTopic = true;
- lineError = playSequence(kMrPottsLodgeTopicLines, ARRAYSIZE(kMrPottsLodgeTopicLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsLodgeTopicLines, ARRAYSIZE(kMrPottsLodgeTopicLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x1fe);
@@ -958,7 +929,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x1ff)) {
- lineError = playMrPottsLine(0x2aaf, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2aaf, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x200);
@@ -967,7 +938,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kMrPottsMoynahanTopicResponseLines,
ARRAYSIZE(kMrPottsMoynahanTopicResponseLines))) {
if (!runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
- lineError = playMrPottsLine(0x2abb, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2abb, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
assignMrPottsTopicBuffer(0x203);
@@ -979,13 +950,13 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (!runtime.startupScript().getFlagValue("KARIN_KIDNAPED") ||
runtime.startupScript().getFlagValue("KARIN_FOUND_ALIVE") ||
runtime.startupScript().getFlagValue("KARIN_FOUND_DEAD")) {
- lineError = playMrPottsLine(0x2bd9, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2bd9, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
- lineError = playSequence(kMrPottsMurderAccusationOpeningLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsMurderAccusationOpeningLines,
ARRAYSIZE(kMrPottsMurderAccusationOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -993,10 +964,10 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
const bool hasMoynahanAccusation = sharedState.moynahanKarinKidnapedDiscussionState;
const bool hasWeddingMatchesAccusation = hasInventoryItem(kWeddingMatchesObjectName);
if (!hasMoynahanAccusation && !hasWeddingMatchesAccusation) {
- lineError = playPcLine(0x2e46, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2e46, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playMrPottsLine(0x2e4a, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2e4a, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
@@ -1027,11 +998,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (accusationResponseIndex == 1) {
- lineError = playMrPottsLine(0x2d7a, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2d7a, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (accusationResponseIndex == moynahanResponseIndex) {
- lineError = playMrPottsLine(0x2d80, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2d80, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1043,11 +1014,11 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2d8e, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2d8e, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2 && sharedState.discussedMrPottsTuesdayNightAlibi) {
- lineError = playMrPottsLine(0x2d93, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2d93, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
lineError = runtime.playDialogueLineWithVariant(0x2d9c, "MRS_POTTS", 1);
@@ -1055,7 +1026,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return lineError;
}
} else if (accusationResponseIndex == weddingMatchesResponseIndex) {
- lineError = playSequence(kMrPottsWeddingMatchesAccusationLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsWeddingMatchesAccusationLines,
ARRAYSIZE(kMrPottsWeddingMatchesAccusationLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1063,7 +1034,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
continue;
}
if (runtime.matchesResponseLine(selectedTopic, 0x214)) {
- lineError = playMrPottsLine(0x2dd3, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2dd3, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1073,9 +1044,9 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2ddf, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2ddf, "MR_POTTS", 1);
} else if (responseIndex == 2) {
- lineError = playMrPottsLine(0x2de4, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2de4, "MR_POTTS", 0);
}
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1083,7 +1054,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
if (runtime.matchesAnyResponseLine(selectedTopic, kMrPottsMolestTopicResponseLines,
ARRAYSIZE(kMrPottsMolestTopicResponseLines))) {
- lineError = playMrPottsLine(0x2def, 4);
+ lineError = runtime.playDialogueLineWithVariant(0x2def, "MR_POTTS", 4);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1093,7 +1064,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playSequence(kMrPottsMolestResponse1OpeningLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsMolestResponse1OpeningLines,
ARRAYSIZE(kMrPottsMolestResponse1OpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1104,17 +1075,17 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2e14, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2e14, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playSequence(kMrPottsMolestResponse2IntroLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsMolestResponse2IntroLines,
ARRAYSIZE(kMrPottsMolestResponse2IntroLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
for (;;) {
- lineError = playMrPottsLine(0x2e2b, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2e2b, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1126,10 +1097,10 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (followupResponseIndex == 1)
continue;
if (followupResponseIndex == 2) {
- lineError = playMrPottsLine(0x2e2f, 3);
+ lineError = runtime.playDialogueLineWithVariant(0x2e2f, "MR_POTTS", 3);
if (lineError.getCode() != Common::kNoError)
return lineError;
- lineError = playPcLine(0x2e34, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2e34, "PC", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
@@ -1137,7 +1108,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
}
}
} else if (responseIndex == 2) {
- lineError = playSequence(kMrPottsMolestAlternativeOpeningLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsMolestAlternativeOpeningLines,
ARRAYSIZE(kMrPottsMolestAlternativeOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1151,14 +1122,13 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
if (runtime.matchesAnyResponseLine(selectedTopic, kMrPottsPeepholeTopicResponseLines,
ARRAYSIZE(kMrPottsPeepholeTopicResponseLines))) {
if (runtime.startupScript().getFlagValue("STEPHANIE_IS_DEAD")) {
- lineError = playMrPottsLine(0x2bd9, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2bd9, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
continue;
}
- lineError = playSequence(kMrPottsPeepholeOpeningLines,
- ARRAYSIZE(kMrPottsPeepholeOpeningLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsPeepholeOpeningLines, ARRAYSIZE(kMrPottsPeepholeOpeningLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1168,27 +1138,26 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
return responseError;
if (responseIndex == 1) {
- lineError = playMrPottsLine(0x2d14, 2);
+ lineError = runtime.playDialogueLineWithVariant(0x2d14, "MR_POTTS", 2);
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 2) {
- lineError = playSequence(kMrPottsPeepholeResponse2Lines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsPeepholeResponse2Lines,
ARRAYSIZE(kMrPottsPeepholeResponse2Lines));
if (lineError.getCode() != Common::kNoError)
return lineError;
} else if (responseIndex == 3) {
- lineError = playMrPottsLine(0x2d28, 1);
+ lineError = runtime.playDialogueLineWithVariant(0x2d28, "MR_POTTS", 1);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
- lineError = playSequence(kMrPottsPeepholeClosingLines,
- ARRAYSIZE(kMrPottsPeepholeClosingLines));
+ lineError = runtime.playDialogueEntrySequence(kMrPottsPeepholeClosingLines, ARRAYSIZE(kMrPottsPeepholeClosingLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
sharedState.confrontedMrPottsAboutSpyhole = true;
- lineError = playSequence(kMrPottsPeepholeFollowupLines,
+ lineError = runtime.playDialogueEntrySequence(kMrPottsPeepholeFollowupLines,
ARRAYSIZE(kMrPottsPeepholeFollowupLines));
if (lineError.getCode() != Common::kNoError)
return lineError;
@@ -1197,7 +1166,7 @@ Common::Error MrPottsDialogueHandler::handleDialogue(DialogueRuntime &runtime,
continue;
}
- lineError = playMrPottsLine(0x2c73, 0);
+ lineError = runtime.playDialogueLineWithVariant(0x2c73, "MR_POTTS", 0);
if (lineError.getCode() != Common::kNoError)
return lineError;
}
diff --git a/engines/harvester/npc/mr_potts_dialogue.h b/engines/harvester/npc/mr_potts_dialogue.h
index f2727b9faa9..fe48f4183d9 100644
--- a/engines/harvester/npc/mr_potts_dialogue.h
+++ b/engines/harvester/npc/mr_potts_dialogue.h
@@ -50,7 +50,6 @@ public:
bool day6KarinFoundAliveFollowupShown = false;
};
- bool matchesNpc(const Common::String &npcName) const override;
void resetState() override {
const int topicBufferLineIndex = _state.topicBufferLineIndex;
_state = MrPottsRoomDialogueState();
diff --git a/engines/harvester/npc/mrs_potts_dialogue.cpp b/engines/harvester/npc/mrs_potts_dialogue.cpp
index a7e0463006a..cfde17bcb02 100644
--- a/engines/harvester/npc/mrs_potts_dialogue.cpp
+++ b/engines/harvester/npc/mrs_potts_dialogue.cpp
@@ -132,35 +132,14 @@ static const int kMrsPottsLodgeTopicResponseLines[] = { 0x247, 0x248 };
} // End of namespace
-bool MrsPottsDialogueHandler::matchesNpc(const Common::String &npcName) const {
- return npcName.equalsIgnoreCase("MRS_POTTS") ||
- npcName.equalsIgnoreCase("MRS_POTTS_ST_BEDRM");
Commit: 8ae6a2999b4614a8960112092c037efe0d7b7a65
https://github.com/scummvm/scummvm/commit/8ae6a2999b4614a8960112092c037efe0d7b7a65
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:06-04:00
Commit Message:
HARVESTER: refactor player state management
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/combat.cpp
engines/harvester/combat.h
engines/harvester/flow.cpp
engines/harvester/input.cpp
engines/harvester/interaction.cpp
engines/harvester/interaction.h
engines/harvester/player.cpp
engines/harvester/player.h
engines/harvester/room_support.h
engines/harvester/scene.cpp
engines/harvester/scene.h
diff --git a/engines/harvester/combat.cpp b/engines/harvester/combat.cpp
index c3b20c1ad67..ee6e1325fa4 100644
--- a/engines/harvester/combat.cpp
+++ b/engines/harvester/combat.cpp
@@ -737,10 +737,10 @@ MonsterRecord *Combat::findProjectileContactMonsterTarget(RoomSetupState &state,
return bestMonster;
}
-void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, RoomPlayerState &playerState,
+void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player &player,
EntityManager *entityManager, bool attackLeft, bool attackRight, bool attackUp, bool attackDown) const {
- playerState.attackTargetName.clear();
- playerState.attackTargetClassId = -1;
+ const RoomPlayerState &playerState = player.getState();
+ player.clearAttackTarget();
if (!playerState.entity)
return;
@@ -838,8 +838,7 @@ void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, RoomPla
return;
}
- playerState.attackTargetName = bestName;
- playerState.attackTargetClassId = bestClassId;
+ player.captureAttackTarget(bestName, bestClassId);
debugC(1, kDebugCombat,
"Harvester: combat player keyboard target capture class='%s' name='%s' input=(L=%d R=%d U=%d D=%d) facing=%d target_rect=(%d,%d)-(%d,%d)",
describeCombatTargetClass(bestClassId), bestName.c_str(),
@@ -902,11 +901,11 @@ MonsterRecord *Combat::resolveKillTarget(RoomSetupState &state, const RoomPlayer
return bestMonster;
}
-void Combat::capturePlayerAttackTarget(RoomSetupState &state, RoomPlayerState &playerState,
+void Combat::capturePlayerAttackTarget(RoomSetupState &state, Player &player,
EntityManager *entityManager, const Common::Point &mousePos, const NpcRecord *hoverNpc) const {
+ const RoomPlayerState &playerState = player.getState();
if (hoverNpc) {
- playerState.attackTargetName = hoverNpc->npcName;
- playerState.attackTargetClassId = kEntityClassNpc;
+ player.captureAttackTarget(hoverNpc->npcName, kEntityClassNpc);
debugC(1, kDebugCombat,
"Harvester: combat player target capture class='npc' name='%s' cursor=(%d,%d)",
playerState.attackTargetName.c_str(), mousePos.x, mousePos.y);
@@ -914,8 +913,7 @@ void Combat::capturePlayerAttackTarget(RoomSetupState &state, RoomPlayerState &p
}
if (MonsterRecord *monster = findMonsterTargetAtPoint(state, entityManager, mousePos)) {
- playerState.attackTargetName = monster->monsterName;
- playerState.attackTargetClassId = kEntityClassMonster;
+ player.captureAttackTarget(monster->monsterName, kEntityClassMonster);
debugC(1, kDebugCombat,
"Harvester: combat player target capture class='monster' name='%s' cursor=(%d,%d)",
playerState.attackTargetName.c_str(), mousePos.x, mousePos.y);
@@ -927,11 +925,11 @@ void Combat::capturePlayerAttackTarget(RoomSetupState &state, RoomPlayerState &p
mousePos.x, mousePos.y);
}
-void Combat::captureOverlappingNpcAttackTarget(RoomSetupState &state, RoomPlayerState &playerState, EntityManager *entityManager) const {
+void Combat::captureOverlappingNpcAttackTarget(RoomSetupState &state, Player &player, EntityManager *entityManager) const {
+ const RoomPlayerState &playerState = player.getState();
if (playerState.attackTargetClassId < 0 && !Player::isProjectileCombatLoadout(playerState.combatLoadout)) {
if (NpcRecord *fallbackNpc = findOverlappingNpcTarget(state, playerState, entityManager)) {
- playerState.attackTargetName = fallbackNpc->npcName;
- playerState.attackTargetClassId = kEntityClassNpc;
+ player.captureAttackTarget(fallbackNpc->npcName, kEntityClassNpc);
}
}
}
@@ -946,8 +944,9 @@ NpcRecord *Combat::selectNpcAttackContactTarget(RoomSetupState &state, const Roo
return npc;
}
-MonsterRecord *Combat::selectMonsterAttackContactTarget(RoomSetupState &state, RoomPlayerState &playerState,
+MonsterRecord *Combat::selectMonsterAttackContactTarget(RoomSetupState &state, Player &player,
EntityManager *entityManager, Entity *&monsterEntity) const {
+ const RoomPlayerState &playerState = player.getState();
MonsterRecord *monster = nullptr;
if (playerState.attackTargetClassId == kEntityClassMonster)
monster = findRoomMonsterRecordByName(state, playerState.attackTargetName);
@@ -958,8 +957,7 @@ MonsterRecord *Combat::selectMonsterAttackContactTarget(RoomSetupState &state, R
} else if (playerState.attackTargetClassId < 0) {
monster = findProjectileContactMonsterTarget(state, playerState, entityManager);
if (monster) {
- playerState.attackTargetName = monster->monsterName;
- playerState.attackTargetClassId = kEntityClassMonster;
+ player.captureAttackTarget(monster->monsterName, kEntityClassMonster);
}
} else {
monster = nullptr;
@@ -1173,8 +1171,9 @@ void Combat::startMonsterHitReaction(HarvesterEngine &engine,
}
Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupState &state,
- RoomPlayerState &playerState, EntityManager *entityManager, const Common::Point &mousePos,
+ Player &player, EntityManager *entityManager, const Common::Point &mousePos,
CombatEffects &combatEffects, Interaction &interactionProcessor, bool &needsRedraw) {
+ const RoomPlayerState &playerState = player.getState();
if (!engine.isCombatDebugEnabled())
return Common::kNoError;
MonsterRecord *monster = resolveKillTarget(state, playerState, entityManager, mousePos);
@@ -1202,8 +1201,7 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
if (playerState.attackTargetClassId == kEntityClassMonster &&
playerState.attackTargetName.equalsIgnoreCase(monster->monsterName)) {
- playerState.attackTargetName.clear();
- playerState.attackTargetClassId = -1;
+ player.clearAttackTarget();
}
debugC(1, kDebugCombat,
@@ -1256,9 +1254,10 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
}
Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState, EntityManager *entityManager,
+ Player &player, EntityManager *entityManager,
SceneEntities &sceneRuntime, CombatEffects &combatEffects, const CheatSystem &cheats,
InteractionCallbacks &callbacks, Interaction &interactionProcessor, bool &needsRedraw) {
+ const RoomPlayerState &playerState = player.getState();
if (!entityManager)
return Common::kNoError;
@@ -1413,17 +1412,9 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
damageDisabled ? 1 : 0);
if (damageLanded > 0 && playerState.entity) {
combatEffects.spawnCombatDamagePopup(*playerState.entity, playerState.entity->getName(), damageLanded);
- if (idleState.entity) {
- idleState.entity->setVisible(false);
- idleState.entity->setAnimationRate(0);
- }
- idleState.active = false;
- idleState.loopStarted = false;
- idleState.exiting = false;
- idleState.restoreFacing = -1;
- playerState.entity->setVisible(true);
+ player.cancelIdleAnimation();
if (playerHitPointsAfter > 0 &&
- Player::startHitAnimation(engine, playerState, combatState.attackFirstFrame)) {
+ player.startHitAnimation(engine, combatState.attackFirstFrame)) {
callbacks.notePlayerActivity();
}
}
@@ -1583,17 +1574,18 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
}
Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
- RoomSetupState &state, RoomPlayerState &playerState,
+ RoomSetupState &state, Player &player,
EntityManager *entityManager, SceneEntities &sceneRuntime,
CombatEffects &combatEffects,
Interaction &interactionProcessor, bool &needsRedraw) {
+ const RoomPlayerState &playerState = player.getState();
if (!playerState.attackActive || playerState.attackContactResolved || !playerState.entity ||
playerState.attackContactFrame < 0 ||
playerState.entity->getCurrentFrame() < playerState.attackContactFrame) {
return Common::kNoError;
}
- playerState.attackContactResolved = true;
+ player.markAttackContactResolved();
const int damageType = Player::resolveCombatLoadoutDamageType(playerState.combatLoadout);
const int damageAmount = Player::resolveCombatLoadoutDamageAmount(playerState.combatLoadout);
debugC(1, kDebugCombat,
@@ -1606,7 +1598,7 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
if (!script)
return Common::kNoError;
- captureOverlappingNpcAttackTarget(state, playerState, entityManager);
+ captureOverlappingNpcAttackTarget(state, player, entityManager);
if (playerState.attackTargetClassId == kEntityClassNpc) {
Entity *npcEntity = nullptr;
NpcRecord *npc = selectNpcAttackContactTarget(state, playerState, entityManager, npcEntity);
@@ -1658,7 +1650,7 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
}
Entity *monsterEntity = nullptr;
- MonsterRecord *monster = selectMonsterAttackContactTarget(state, playerState, entityManager, monsterEntity);
+ MonsterRecord *monster = selectMonsterAttackContactTarget(state, player, entityManager, monsterEntity);
if (!monster || !monsterEntity) {
debugC(1, kDebugCombat,
"Harvester: combat player attack missed class='monster' target='%s' reason='no reachable monster'",
diff --git a/engines/harvester/combat.h b/engines/harvester/combat.h
index cb04d5f37ea..4d8e9d2d8df 100644
--- a/engines/harvester/combat.h
+++ b/engines/harvester/combat.h
@@ -35,6 +35,8 @@ class CombatEffects;
class InteractionCallbacks;
class Interaction;
class SceneEntities;
+class Player;
+struct RoomPlayerState;
extern const int kRoomMonsterAnimationRate;
extern const int kNativeMonsterAttackAnimationRate;
@@ -137,29 +139,29 @@ public:
void commitMonsterCombatStatesForSceneChange(Common::Array<MonsterCombatState> &&states);
void resetForSceneRefresh(const RoomSetupState &state);
- void capturePlayerAttackTargetForKeyboard(RoomSetupState &state, RoomPlayerState &playerState,
+ void capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player &player,
EntityManager *entityManager, bool attackLeft, bool attackRight, bool attackUp, bool attackDown) const;
MonsterRecord *resolveKillTarget(RoomSetupState &state, const RoomPlayerState &playerState,
EntityManager *entityManager, const Common::Point &mousePos) const;
// The caller clears the captured target before resolving the room hover state.
- void capturePlayerAttackTarget(RoomSetupState &state, RoomPlayerState &playerState,
+ void capturePlayerAttackTarget(RoomSetupState &state, Player &player,
EntityManager *entityManager, const Common::Point &mousePos, const NpcRecord *hoverNpc) const;
- void captureOverlappingNpcAttackTarget(RoomSetupState &state, RoomPlayerState &playerState, EntityManager *entityManager) const;
+ void captureOverlappingNpcAttackTarget(RoomSetupState &state, Player &player, EntityManager *entityManager) const;
NpcRecord *selectNpcAttackContactTarget(RoomSetupState &state, const RoomPlayerState &playerState,
EntityManager *entityManager, Entity *&npcEntity) const;
- MonsterRecord *selectMonsterAttackContactTarget(RoomSetupState &state, RoomPlayerState &playerState,
+ MonsterRecord *selectMonsterAttackContactTarget(RoomSetupState &state, Player &player,
EntityManager *entityManager, Entity *&monsterEntity) const;
Common::Error killDebugActiveMonster(HarvesterEngine &engine, RoomSetupState &state,
- RoomPlayerState &playerState, EntityManager *entityManager, const Common::Point &mousePos,
+ Player &player, EntityManager *entityManager, const Common::Point &mousePos,
CombatEffects &combatEffects, Interaction &interactionProcessor, bool &needsRedraw);
Common::Error updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState, EntityManager *entityManager,
+ Player &player, EntityManager *entityManager,
SceneEntities &sceneRuntime, CombatEffects &combatEffects, const CheatSystem &cheats,
InteractionCallbacks &callbacks, Interaction &interactionProcessor, bool &needsRedraw);
Common::Error resolvePlayerAttackContact(HarvesterEngine &engine,
- RoomSetupState &state, RoomPlayerState &playerState,
+ RoomSetupState &state, Player &player,
EntityManager *entityManager, SceneEntities &sceneRuntime,
CombatEffects &combatEffects,
Interaction &interactionProcessor, bool &needsRedraw);
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 21bc79e07d5..83844608f46 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -1257,22 +1257,17 @@ void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
Entity *player = entityManager->findSceneEntityByName(kPlayerActorEntityName);
if (player && foundFloorProbe && floorHover.cursorSequence == kCursorSequenceWalk) {
- RoomPlayerState probePlayer;
- probePlayer.entity = player;
- probePlayer.centerX = scene.state.playerSpawnX;
- probePlayer.bottomY = scene.state.playerSpawnY;
- probePlayer.z = (float)scene.state.playerSpawnZ;
- probePlayer.facing = scene.state.playerFacing;
- Player::setMoveTargetFromScreenPoint(scene.state, probePlayer, floorProbe.x, floorProbe.y);
- for (int i = 0; i < 32 && probePlayer.hasMoveTarget; ++i)
- (void)Player::stepMoveTarget(
- engine, scene.state, scene.sceneObjects, scene.sceneAnimations, probePlayer);
+ Player probePlayer;
+ probePlayer.initialize(scene.state, player, 0);
+ probePlayer.setMoveTargetFromScreenPoint(scene.state, floorProbe.x, floorProbe.y);
+ for (int i = 0; i < 32 && probePlayer.getState().hasMoveTarget; ++i)
+ (void)probePlayer.stepMoveTarget(engine, scene.state, scene.sceneObjects, scene.sceneAnimations);
const Common::Rect movedRect = player->getScreenRect();
debugC(1, kDebugPlayer,
"Harvester: startup probe movement room='%s' target=(%d,%d) final_rect=(%d,%d)-(%d,%d) z=%.2f",
scene.state.roomName.c_str(), floorProbe.x, floorProbe.y,
- movedRect.left, movedRect.top, movedRect.right, movedRect.bottom, (double)probePlayer.z);
+ movedRect.left, movedRect.top, movedRect.right, movedRect.bottom, (double)probePlayer.getState().z);
player->setCurrentFrame(Player::resolveFacingFrame(scene.state.playerFacing));
(void)applyRoomActorPlacement(scene.state, *player,
@@ -2180,26 +2175,16 @@ bool Flow::populateRoomSceneEntities(RoomSetupState &state,
state.entranceName.c_str());
}
if (reusedPlayer) {
- RoomPlayerState playerState;
- playerState.entity = player;
- playerState.centerX = state.playerSpawnX;
- playerState.bottomY = state.playerSpawnY;
- playerState.z = (float)state.playerSpawnZ;
- playerState.facing = state.playerFacing;
- playerState.combatLoadout = -1;
- (void)Player::syncCombatLoadoutVisual(_engine, state, playerState, playerCombatLoadout);
+ Player loadoutPlayer;
+ loadoutPlayer.initialize(state, player, -1);
+ (void)loadoutPlayer.syncCombatLoadoutVisual(_engine, state, playerCombatLoadout);
}
- RoomPlayerState playerSpawnState;
- playerSpawnState.entity = player;
- playerSpawnState.centerX = state.playerSpawnX;
- playerSpawnState.bottomY = state.playerSpawnY;
- playerSpawnState.z = (float)state.playerSpawnZ;
- playerSpawnState.facing = state.playerFacing;
- if (Player::resolveBlockedStartupSpawn(
- _engine, state, drawableObjects, drawableAnimations, playerSpawnState)) {
- state.playerSpawnX = playerSpawnState.centerX;
- state.playerSpawnY = playerSpawnState.bottomY;
- state.playerSpawnZ = (int)playerSpawnState.z;
+ Player spawnPlayer;
+ spawnPlayer.initialize(state, player, 0);
+ if (spawnPlayer.resolveBlockedStartupSpawn(_engine, state, drawableObjects, drawableAnimations)) {
+ state.playerSpawnX = spawnPlayer.getState().centerX;
+ state.playerSpawnY = spawnPlayer.getState().bottomY;
+ state.playerSpawnZ = (int)spawnPlayer.getState().z;
}
if (reusedPlayer)
entityManager->adoptSceneEntity(player);
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index 28aebb316b5..d4db61fbeb5 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -114,7 +114,7 @@ void Input::queueCombatLoadoutStatusMessage(const Common::String &message, bool
}
bool Input::openInventoryOverlay() {
- RoomPlayerState &playerState = _session.getPlayerState();
+ Player &player = _session.getPlayer();
InputState &inputState = _session.getInputState();
inputState.moveLeft = false;
@@ -123,19 +123,16 @@ bool Input::openInventoryOverlay() {
inputState.moveDown = false;
_session.clearPendingRegionInteraction();
(void)_session.cancelPlayerAttackAnimation();
- playerState.hasMoveTarget = false;
- playerState.turnActive = false;
- playerState.turnTargetFacing = -1;
+ player.cancelMovement();
if (!_roomItems.stowCarriedRoomItemToInventory())
return false;
return _inventory.open();
}
void Input::capturePlayerAttackTarget() {
- RoomPlayerState &playerState = _session.getPlayerState();
+ Player &player = _session.getPlayer();
- playerState.attackTargetName.clear();
- playerState.attackTargetClassId = -1;
+ player.clearAttackTarget();
const RoomHoverState hoverState = resolveRoomHoverState(
_engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs, _scene.sceneRegions,
@@ -157,12 +154,13 @@ void Input::handleMouseMove(bool &needsRedraw) {
}
InputResult Input::handleRightButtonDown(bool &needsRedraw) {
- RoomPlayerState &playerState = _session.getPlayerState();
- RoomIdleAnimationState &idleState = _session.getIdleState();
+ Player &player = _session.getPlayer();
+ const RoomPlayerState &playerState = player.getState();
+ const RoomIdleAnimationState &idleState = player.getIdleState();
_session.notePlayerActivity();
if (idleState.active || idleState.exiting) {
- if (Player::requestIdleAnimationExit(_scene.state, playerState, idleState))
+ if (player.requestIdleAnimationExit(_scene.state))
needsRedraw = true;
return InputResult();
}
@@ -202,13 +200,7 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
_presentationState.closeInventoryAfterCombatLoadoutStatus = true;
}
_session.captureCurrentSaveState();
- if (playerState.entity) {
- (void)Player::syncCombatLoadoutVisual(_engine, _scene.state, playerState,
- _engine.getScript()->getPlayerCombatLoadout());
- } else if (_engine.getScript()) {
- playerState.combatLoadout =
- _engine.getScript()->getPlayerCombatLoadout();
- }
+ player.syncCombatLoadout(_engine, _scene.state);
if (!_inventory.refresh())
return InputResult::leaveRoom(Common::kReadingFailed);
}
@@ -282,17 +274,10 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
Script *script = _engine.getScript();
if (!_presentationState.showingInspectText && !_session.isPlayerCombatLocked() && script && playerState.entity &&
script->getPlayerCurrentHitPoints() > 0 && !script->isPlayerControlPaused()) {
- playerState.hasMoveTarget = false;
- playerState.turnActive = false;
- playerState.turnTargetFacing = -1;
- playerState.turnFirstFrame = -1;
- playerState.turnLastFrame = -1;
- playerState.turnEndFrame = -1;
- playerState.turnPlayBackwards = false;
- (void)Player::syncCombatLoadoutVisual(_engine, _scene.state, playerState,
- script->getPlayerCombatLoadout());
+ player.cancelMovementForAttack();
+ (void)player.syncCombatLoadoutVisual(_engine, _scene.state, script->getPlayerCombatLoadout());
capturePlayerAttackTarget();
- if (Player::startAttackAnimation(_scene.state, playerState, _flow._mousePos)) {
+ if (player.startAttackAnimation(_scene.state, _flow._mousePos)) {
debugC(1, kDebugCombat,
"Harvester: combat player attack start loadout=%d weapon='%s' damage=%d damage_type='%s' target_class='%s' target='%s' cursor=(%d,%d)",
playerState.combatLoadout,
@@ -303,8 +288,7 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
playerState.attackTargetName.c_str(), _flow._mousePos.x, _flow._mousePos.y);
needsRedraw = true;
} else {
- playerState.attackTargetName.clear();
- playerState.attackTargetClassId = -1;
+ player.clearAttackTarget();
}
}
return InputResult();
@@ -319,8 +303,9 @@ void Input::handleLeftButtonUp() {
}
InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
- RoomPlayerState &playerState = _session.getPlayerState();
- RoomIdleAnimationState &idleState = _session.getIdleState();
+ Player &player = _session.getPlayer();
+ const RoomPlayerState &playerState = player.getState();
+ const RoomIdleAnimationState &idleState = player.getIdleState();
InputState &inputState = _session.getInputState();
const uint32 now = Player::getRuntimeClockTicks();
@@ -329,7 +314,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
now - inputState.lastLeftButtonReleaseTick < kRoomExitFastClickWindowTicks;
_session.notePlayerActivity();
if (idleState.active || idleState.exiting) {
- if (Player::requestIdleAnimationExit(_scene.state, playerState, idleState))
+ if (player.requestIdleAnimationExit(_scene.state))
needsRedraw = true;
return InputResult();
}
@@ -486,9 +471,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
inputState.moveRight = false;
inputState.moveUp = false;
inputState.moveDown = false;
- playerState.hasMoveTarget = false;
- playerState.turnActive = false;
- playerState.turnTargetFacing = -1;
+ player.cancelMovement();
bool didTransition = false;
Common::Error dialogueError = _interactionProcessor.runScriptedDialogue(
hoverState.npc->npcName, Common::String(), Common::String(), didTransition);
@@ -538,7 +521,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
playerState.centerX, playerState.bottomY, (double)playerState.z,
playerRect.left, playerRect.top, playerRect.right, playerRect.bottom);
}
- Player::setMoveTargetFromScreenPoint(_scene.state, playerState, _flow._mousePos.x, _flow._mousePos.y);
+ player.setMoveTargetFromScreenPoint(_scene.state, _flow._mousePos.x, _flow._mousePos.y);
if (_engine.isPathfindingDebugEnabled()) {
debugC(1, kDebugPathfinding,
"Harvester: pathfinding click target room='%s' mouse=(%d,%d) target=(%d,%d,z=%.2f)",
@@ -577,9 +560,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
debug(1, "Harvester: unsupported IDENT textbox '%s' for object '%s'",
resolvedInspectText.boxName.c_str(), clickedObject->objectName.c_str());
}
- playerState.hasMoveTarget = false;
- playerState.turnActive = false;
- playerState.turnTargetFacing = -1;
+ player.cancelMovement();
needsRedraw = true;
return InputResult();
}
@@ -617,8 +598,8 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
}
InputResult Input::handleKeyDown(const Common::KeyState &key, bool &needsRedraw) {
- RoomPlayerState &playerState = _session.getPlayerState();
- RoomIdleAnimationState &idleState = _session.getIdleState();
+ Player &player = _session.getPlayer();
+ const RoomIdleAnimationState &idleState = player.getIdleState();
InputState &inputState = _session.getInputState();
if (_presentationState.showingInspectText) {
@@ -635,7 +616,7 @@ InputResult Input::handleKeyDown(const Common::KeyState &key, bool &needsRedraw)
if (key.hasFlags(Common::KBD_CTRL))
inputState.attackModifierHeld = true;
if (idleState.active || idleState.exiting) {
- if (Player::requestIdleAnimationExit(_scene.state, playerState, idleState))
+ if (player.requestIdleAnimationExit(_scene.state))
needsRedraw = true;
return InputResult();
}
@@ -734,9 +715,7 @@ InputResult Input::handleKeyDown(const Common::KeyState &key, bool &needsRedraw)
inputState.moveUp = false;
inputState.moveDown = false;
_session.clearPendingRegionInteraction();
- playerState.hasMoveTarget = false;
- playerState.turnActive = false;
- playerState.turnTargetFacing = -1;
+ player.cancelMovement();
_session.captureCurrentSaveState();
Graphics::Screen *activeScreen = _engine.getScreen();
if (!activeScreen)
diff --git a/engines/harvester/interaction.cpp b/engines/harvester/interaction.cpp
index 77d949f5cbc..2cc52ad8511 100644
--- a/engines/harvester/interaction.cpp
+++ b/engines/harvester/interaction.cpp
@@ -348,12 +348,12 @@ Common::Error ItemInteractions::handleRoomItemPickup(const ObjectRecord &object,
}
Interaction::Interaction(HarvesterEngine &engine, Flow &flow,
- SceneState &scene, RoomPlayerState &playerState,
+ SceneState &scene, Player &player,
Common::String &pendingRegionName, Common::String &pendingRoomChange,
bool &pendingRoomChangeIsRoomName, bool &pendingRoomChangeUsesSavedRoomState,
SaveRoomState &pendingRoomChangeSavedRoomState, bool canExitCloseupToParent,
InteractionCallbacks &callbacks)
- : _engine(engine), _flow(flow), _scene(scene), _playerState(playerState),
+ : _engine(engine), _flow(flow), _scene(scene), _player(player),
_pendingRegionName(pendingRegionName), _pendingRoomChange(pendingRoomChange),
_pendingRoomChangeIsRoomName(pendingRoomChangeIsRoomName),
_pendingRoomChangeUsesSavedRoomState(pendingRoomChangeUsesSavedRoomState),
@@ -362,13 +362,14 @@ Interaction::Interaction(HarvesterEngine &engine, Flow &flow,
}
void Interaction::queueRegionInteraction(const RegionRecord ®ion, const Common::Point &mousePos) {
+ const RoomPlayerState &playerState = _player.getState();
_pendingRegionName = region.regionName;
- if (!_playerState.entity)
+ if (!playerState.entity)
return;
- const bool playerOverlapsRegion = doesPlayerOverlapRegion(*_playerState.entity, region);
+ const bool playerOverlapsRegion = doesPlayerOverlapRegion(*playerState.entity, region);
if (_engine.isPathfindingDebugEnabled()) {
- const Common::Rect playerRect = _playerState.entity->getScreenRect();
+ const Common::Rect playerRect = playerState.entity->getScreenRect();
const Common::Rect regionBounds(region.left, region.top, region.right + 1, region.bottom + 1);
debugC(1, kDebugPathfinding,
"Harvester: pathfinding region click room='%s' mouse=(%d,%d) region='%s' bounds=(%d,%d)-(%d,%d) z=[%d,%d] start=%d cursor=%d desired_facing=%d player=(%d,%d,z=%.2f) player_rect=(%d,%d)-(%d,%d) overlaps=%d action='%s'",
@@ -377,33 +378,33 @@ void Interaction::queueRegionInteraction(const RegionRecord ®ion, const Commo
regionBounds.left, regionBounds.top, regionBounds.right, regionBounds.bottom,
region.minZ, region.maxZ, region.startEnabled, region.cursorEnabled,
region.desiredFacing,
- _playerState.centerX, _playerState.bottomY, (double)_playerState.z,
+ playerState.centerX, playerState.bottomY, (double)playerState.z,
playerRect.left, playerRect.top, playerRect.right, playerRect.bottom,
playerOverlapsRegion, region.actionTag.c_str());
}
- if (playerOverlapsRegion && doesPlayerFacingMatchRegion(_playerState.facing, region))
+ if (playerOverlapsRegion && doesPlayerFacingMatchRegion(playerState.facing, region))
return;
- Player::setRegionMoveTarget(_scene.state, _playerState,
- Player::resolveRegionTargetX(_scene.state, region, _playerState),
- Player::resolveRegionTargetZ(region));
+ _player.setRegionMoveTarget(_scene.state,
+ Player::resolveRegionTargetX(_scene.state, region, playerState), Player::resolveRegionTargetZ(region));
if (_engine.isPathfindingDebugEnabled()) {
debugC(1, kDebugPathfinding,
"Harvester: pathfinding region target room='%s' region='%s' target=(%d,%d,z=%.2f)",
_scene.state.roomName.c_str(), region.regionName.c_str(),
- _playerState.targetX, _playerState.targetBottomY, (double)_playerState.targetZ);
+ playerState.targetX, playerState.targetBottomY, (double)playerState.targetZ);
}
}
Common::Error Interaction::runRegionInteraction(const RegionRecord ®ion,
InventorySystem &inventory, bool &needsRedraw) {
+ const RoomPlayerState &playerState = _player.getState();
InteractionResult interaction;
if (!_engine.getScript()->resolveRegionInteraction(region, interaction, _scene.state.roomName))
return Common::kNoError;
debugC(2, kDebugRoom,
"Harvester: region interaction room='%s' region='%s' action='%s' player=(%d,%d,z=%.2f) next_room='%s'",
_scene.state.roomName.c_str(), region.regionName.c_str(), region.actionTag.c_str(),
- _playerState.centerX, _playerState.bottomY, (double)_playerState.z,
+ playerState.centerX, playerState.bottomY, (double)playerState.z,
interaction.nextRoomName.c_str());
bool didTransition = false;
@@ -421,7 +422,8 @@ Common::Error Interaction::runRegionInteraction(const RegionRecord ®ion,
}
Common::Error Interaction::tryActivatePendingRegion(InventorySystem &inventory, bool &needsRedraw) {
- if (_pendingRegionName.empty() || !_playerState.entity)
+ const RoomPlayerState &playerState = _player.getState();
+ if (_pendingRegionName.empty() || !playerState.entity)
return Common::kNoError;
const RegionRecord *region = findSceneRegionByName(_scene.sceneRegions, _pendingRegionName);
@@ -429,11 +431,11 @@ Common::Error Interaction::tryActivatePendingRegion(InventorySystem &inventory,
_pendingRegionName.clear();
return Common::kNoError;
}
- if (!doesPlayerOverlapRegion(*_playerState.entity, *region))
+ if (!doesPlayerOverlapRegion(*playerState.entity, *region))
return Common::kNoError;
- if (!doesPlayerFacingMatchRegion(_playerState.facing, *region)) {
- if (!_playerState.hasMoveTarget && !_playerState.turnActive && region->desiredFacing >= 0)
- (void)Player::startTurnAnimation(_playerState, region->desiredFacing);
+ if (!doesPlayerFacingMatchRegion(playerState.facing, *region)) {
+ if (!playerState.hasMoveTarget && !playerState.turnActive && region->desiredFacing >= 0)
+ (void)_player.startTurnAnimation(region->desiredFacing);
return Common::kNoError;
}
@@ -442,15 +444,16 @@ Common::Error Interaction::tryActivatePendingRegion(InventorySystem &inventory,
}
Common::Error Interaction::tryActivatePassiveRegion(InventorySystem &inventory, bool &needsRedraw) {
- if (!_playerState.entity)
+ const RoomPlayerState &playerState = _player.getState();
+ if (!playerState.entity)
return Common::kNoError;
for (const RegionRecord ®ion : _scene.sceneRegions) {
if (!region.startEnabled)
continue;
- if (!doesPlayerOverlapRegion(*_playerState.entity, region))
+ if (!doesPlayerOverlapRegion(*playerState.entity, region))
continue;
- if (!doesPlayerFacingMatchRegion(_playerState.facing, region))
+ if (!doesPlayerFacingMatchRegion(playerState.facing, region))
continue;
_callbacks.stopPlayerRegionInteraction();
@@ -488,19 +491,18 @@ Common::Error Interaction::handleCombatInteraction(const InteractionResult &inte
Common::Error Interaction::handleInteractionResult(const InteractionResult &interaction,
bool &didTransition, const Common::String &usedItemName, bool interruptPlayerMovement) {
+ const RoomPlayerState &playerState = _player.getState();
didTransition = false;
if (interruptPlayerMovement) {
- _playerState.hasMoveTarget = false;
- _playerState.turnActive = false;
- _playerState.turnTargetFacing = -1;
+ _player.cancelMovement();
_pendingRegionName.clear();
- } else if (_playerState.hasMoveTarget || _playerState.turnActive) {
+ } else if (playerState.hasMoveTarget || playerState.turnActive) {
debugC(2, kDebugPlayer,
"Harvester: background action preserving player movement room='%s' pos=(%d,%d,z=%.2f) target=(%d,%d,z=%.2f) region='%s' turning=%d",
- _scene.state.roomName.c_str(), _playerState.centerX, _playerState.bottomY,
- _playerState.z, _playerState.targetX, _playerState.targetBottomY,
- _playerState.targetZ, _pendingRegionName.c_str(), _playerState.turnActive);
+ _scene.state.roomName.c_str(), playerState.centerX, playerState.bottomY,
+ playerState.z, playerState.targetX, playerState.targetBottomY,
+ playerState.targetZ, _pendingRegionName.c_str(), playerState.turnActive);
}
if (interaction.requestDemoEnding) {
Common::Error endingError = _flow.runDemoEnding();
@@ -689,15 +691,15 @@ Common::Error Interaction::handleInteractionResult(const InteractionResult &inte
if (interaction.requestPlayerGotoXZ)
_callbacks.applyPlayerGotoXZ(interaction.playerGotoX, interaction.playerGotoZ);
else if (interaction.requestPlayerGotoZ)
- _callbacks.applyPlayerGotoXZ(_playerState.centerX, interaction.playerGotoZ);
+ _callbacks.applyPlayerGotoXZ(playerState.centerX, interaction.playerGotoZ);
if (!interaction.moveEntityToPlayerZName.empty()) {
EntityManager *entityManager = _engine.getRuntimeEntities();
Entity *entity = entityManager
? entityManager->findSceneEntityByName(interaction.moveEntityToPlayerZName)
: nullptr;
- if (entity && _playerState.entity) {
- entity->setPosition(entity->getX(), entity->getY(), _playerState.entity->getZ());
+ if (entity && playerState.entity) {
+ entity->setPosition(entity->getX(), entity->getY(), playerState.entity->getZ());
entityManager->reinsertSceneEntity(entity);
debugC(1, kDebugPlayer, "Harvester: MOVE_BM2PCZ entity='%s' z=%.2f",
interaction.moveEntityToPlayerZName.c_str(), entity->getZ());
diff --git a/engines/harvester/interaction.h b/engines/harvester/interaction.h
index 419031cf7d8..23150d27f58 100644
--- a/engines/harvester/interaction.h
+++ b/engines/harvester/interaction.h
@@ -34,6 +34,7 @@ class HarvesterEngine;
class InventorySystem;
class Interaction;
class SceneEntities;
+class Player;
struct IndexedBitmap;
extern const char *const kExitCloseupPendingRoomChange;
@@ -102,7 +103,7 @@ private:
class Interaction {
public:
Interaction(HarvesterEngine &engine, Flow &flow, SceneState &scene,
- RoomPlayerState &playerState, Common::String &pendingRegionName,
+ Player &player, Common::String &pendingRegionName,
Common::String &pendingRoomChange, bool &pendingRoomChangeIsRoomName,
bool &pendingRoomChangeUsesSavedRoomState, SaveRoomState &pendingRoomChangeSavedRoomState,
bool canExitCloseupToParent, InteractionCallbacks &callbacks);
@@ -125,7 +126,7 @@ private:
HarvesterEngine &_engine;
Flow &_flow;
SceneState &_scene;
- RoomPlayerState &_playerState;
+ Player &_player;
Common::String &_pendingRegionName;
Common::String &_pendingRoomChange;
bool &_pendingRoomChangeIsRoomName;
diff --git a/engines/harvester/player.cpp b/engines/harvester/player.cpp
index 0136cc01933..c039844bd9c 100644
--- a/engines/harvester/player.cpp
+++ b/engines/harvester/player.cpp
@@ -22,6 +22,7 @@
#include <math.h>
#include "harvester/player.h"
+#include "harvester/combat.h"
#include "common/debug.h"
#include "common/system.h"
@@ -34,6 +35,10 @@ namespace Harvester {
namespace {
+static void syncPlayerAnimationPlacement(RoomPlayerState &playerState);
+static bool setPlayerIdleAnimation(RoomPlayerState &playerState, int facing);
+static void updatePlayerIdleTrigger(RoomIdleAnimationState &idleState);
+
static const char *const kPlayerActorResourcePath = "1:/GRAPHIC/MONSTERS/PC/PC0.ABM";
static const float kRoomPlayerHorizontalMoveBase = 8.0f;
static const float kRoomPlayerHorizontalTargetSlackBase = 50.0f;
@@ -295,7 +300,7 @@ static bool playPlayerHitSound(HarvesterEngine &engine) {
return engine.playSound(kPlayerHitSoundPaths[soundIndex]);
}
-static bool runtimeEntityHasFrameRange(const Entity &entity, int firstFrame, int lastFrame) {
+static bool playerEntityHasFrameRange(const Entity &entity, int firstFrame, int lastFrame) {
if (!entity.hasFrames() || firstFrame < 0 || lastFrame < firstFrame)
return false;
@@ -304,7 +309,7 @@ static bool runtimeEntityHasFrameRange(const Entity &entity, int firstFrame, int
static bool choosePlayerDeathAnimationRange(const Entity &entity, int firstFrame, int lastFrame,
PlayerDeathAnimationRange &range) {
- if (!runtimeEntityHasFrameRange(entity, firstFrame, lastFrame))
+ if (!playerEntityHasFrameRange(entity, firstFrame, lastFrame))
return false;
range = PlayerDeathAnimationRange(firstFrame, lastFrame);
@@ -481,7 +486,7 @@ static bool resolvePlayerHitAnimationRange(const Entity &entity,
return false;
}
- if (!runtimeEntityHasFrameRange(entity, candidate.firstFrame, candidate.lastFrame))
+ if (!playerEntityHasFrameRange(entity, candidate.firstFrame, candidate.lastFrame))
return false;
range = candidate;
@@ -830,7 +835,7 @@ static bool tryApplyPlayerMovement(HarvesterEngine &engine, const RoomSetupState
applyPlayerMovementPlacement(state, playerState, candidateCenterX, candidateBottomY, candidateZ);
playerState.z = candidateZ;
- Player::syncAnimationPlacement(playerState);
+ syncPlayerAnimationPlacement(playerState);
reinsertPlayerSceneEntity(engine, playerState);
return true;
@@ -1011,7 +1016,7 @@ static bool tryApplyPlayerWalkMovement(HarvesterEngine &engine, const RoomSetupS
// Region activation gets the resulting frame before the next blocker response.
applyPlayerMovementPlacement(state, playerState, candidateCenterX, candidateBottomY, candidateZ);
playerState.z = candidateZ;
- Player::syncAnimationPlacement(playerState);
+ syncPlayerAnimationPlacement(playerState);
reinsertPlayerSceneEntity(engine, playerState);
return true;
}
@@ -1040,7 +1045,7 @@ static void setMoveTargetInternal(const RoomSetupState &state, RoomPlayerState &
static void notePlayerIdleReset(RoomIdleAnimationState &idleState) {
idleState.resetTick = Player::getRuntimeClockTicks();
- Player::updateIdleTrigger(idleState);
+ updatePlayerIdleTrigger(idleState);
}
static bool setPlayerWalkAnimation(RoomPlayerState &playerState, int facing) {
@@ -1115,7 +1120,7 @@ static bool finishPlayerIdleAnimation(const RoomSetupState &state, RoomPlayerSta
if (playerState.entity) {
playerState.entity->setVisible(true);
if (idleState.restoreFacing >= 0)
- (void)Player::setIdleAnimation(playerState, idleState.restoreFacing);
+ (void)setPlayerIdleAnimation(playerState, idleState.restoreFacing);
}
idleState.active = false;
@@ -1129,10 +1134,180 @@ static bool finishPlayerIdleAnimation(const RoomSetupState &state, RoomPlayerSta
return true;
}
+static void syncPlayerAnimationPlacement(RoomPlayerState &playerState) {
+ if (!playerState.entity)
+ return;
+
+ const Common::Rect rect = playerState.entity->getScreenRect();
+ const int centerX = rect.left + rect.width() / 2;
+ if (playerState.centerX != centerX || playerState.bottomY != rect.bottom) {
+ debugC(3, kDebugPlayer,
+ "Harvester: player frame bounds frame=%d base=(%d,%d) rect=(%d,%d)-(%d,%d) z=%.2f",
+ playerState.entity->getCurrentFrame(), playerState.entity->getX(), playerState.entity->getY(),
+ rect.left, rect.top, rect.right, rect.bottom, (double)playerState.z);
+ }
+ playerState.centerX = centerX;
+ playerState.bottomY = rect.bottom;
+}
+
+static void updatePlayerIdleTrigger(RoomIdleAnimationState &idleState) {
+ idleState.triggerTick = MAX(idleState.activityTick, idleState.resetTick) + kRoomPlayerIdleDelayTicks;
+}
+
+static bool setPlayerIdleAnimation(RoomPlayerState &playerState, int facing) {
+ if (!playerState.entity)
+ return false;
+
+ const PlayerAnimationRange range = resolvePlayerAnimationRange(facing);
+ const bool changed = playerState.facing != facing ||
+ playerState.entity->getCurrentFrame() != range.idleFrame ||
+ playerState.entity->getAnimationRate() != 0;
+ playerState.facing = facing;
+ playerState.nextMovementTick = 0;
+ playerState.keyboardWalkRequest = -1;
+ playerState.walkHorizontalDirection = 0;
+ playerState.walkDepthDirection = 0;
+ playerState.entity->setAnimationRate(0);
+ playerState.entity->setAnimationFrameRange(range.idleFrame, range.idleFrame, false);
+ playerState.entity->setCurrentFrame(range.idleFrame);
+ if (changed) {
+ debugC(1, kDebugPlayer,
+ "Harvester: player idle animation facing=%d frame=%d",
+ facing, range.idleFrame);
+ }
+ return changed;
+}
+
} // End of anonymous namespace
-void Player::rebindAfterSceneRefresh(const RoomSetupState &state, RoomPlayerState &playerState,
+void Player::initialize(const RoomSetupState &state, Entity *entity, int combatLoadout) {
+ RoomPlayerState &playerState = _state;
+ playerState.entity = entity;
+ playerState.centerX = state.playerSpawnX;
+ playerState.bottomY = state.playerSpawnY;
+ playerState.z = (float)state.playerSpawnZ;
+ playerState.facing = state.playerFacing;
+ playerState.combatLoadout = combatLoadout;
+ playerState.turnActive = false;
+ playerState.turnTargetFacing = -1;
+}
+
+bool Player::isCombatLocked() const {
+ return _state.attackActive || _state.hitActive || _state.deathActive;
+}
+
+void Player::cancelMovement() {
+ _state.hasMoveTarget = false;
+ _state.turnActive = false;
+ _state.turnTargetFacing = -1;
+}
+
+void Player::cancelMovementForAttack() {
+ cancelMovement();
+ _state.turnFirstFrame = -1;
+ _state.turnLastFrame = -1;
+ _state.turnEndFrame = -1;
+ _state.turnPlayBackwards = false;
+}
+
+bool Player::cancelAttackAnimation() {
+ RoomPlayerState &playerState = _state;
+ if (!playerState.attackActive)
+ return false;
+
+ playerState.attackActive = false;
+ playerState.attackFirstFrame = -1;
+ playerState.attackLastFrame = -1;
+ playerState.attackContactFrame = -1;
+ if (!playerState.entity)
+ return false;
+ playerState.attackSoundPlayed = false;
+ playerState.attackSoundPlaybackFrame = -1;
+ playerState.attackContactResolved = false;
+ playerState.attackTargetName.clear();
+ playerState.attackTargetClassId = -1;
+ const int resumeFacing = playerState.attackResumeFacing >= 0
+ ? playerState.attackResumeFacing
+ : (playerState.facing >= 0 ? playerState.facing : 0);
+ playerState.attackResumeFacing = -1;
+ return setIdleAnimation(resumeFacing);
+}
+
+void Player::clearAttackTarget() {
+ _state.attackTargetName.clear();
+ _state.attackTargetClassId = -1;
+}
+
+void Player::captureAttackTarget(const Common::String &name, int classId) {
+ _state.attackTargetName = name;
+ _state.attackTargetClassId = classId;
+}
+
+void Player::markAttackContactResolved() {
+ _state.attackContactResolved = true;
+}
+
+void Player::resetIdleState() {
+ RoomIdleAnimationState &idleState = _idleState;
+ idleState = RoomIdleAnimationState();
+ idleState.activityTick = Player::getRuntimeClockTicks();
+ idleState.resetTick = idleState.activityTick;
+ updatePlayerIdleTrigger(idleState);
+}
+
+void Player::noteActivity() {
+ RoomIdleAnimationState &idleState = _idleState;
+ idleState.activityTick = Player::getRuntimeClockTicks();
+ updatePlayerIdleTrigger(idleState);
+}
+
+void Player::cancelIdleAnimation() {
+ RoomPlayerState &playerState = _state;
+ RoomIdleAnimationState &idleState = _idleState;
+ if (idleState.entity) {
+ idleState.entity->setVisible(false);
+ idleState.entity->setAnimationRate(0);
+ }
+ idleState.active = false;
+ idleState.loopStarted = false;
+ idleState.exiting = false;
+ idleState.restoreFacing = -1;
+ if (playerState.entity)
+ playerState.entity->setVisible(true);
+}
+
+void Player::applyGotoXZ(const RoomSetupState &state, EntityManager *entityManager, int x, int z) {
+ RoomPlayerState &playerState = _state;
+ playerState.hasMoveTarget = false;
+ playerState.turnActive = false;
+ playerState.turnTargetFacing = -1;
+ playerState.centerX = x;
+ playerState.z = (float)z;
+ playerState.bottomY = mapRoomDepthToScreenYForCombat(
+ state, playerState.z, playerState.bottomY);
+ Common::Rect screenRect;
+ bool hasScreenRect = false;
+ float depthScale = 0.0f;
+ if (playerState.entity) {
+ (void)applyRoomActorPlacement(state, *playerState.entity,
+ playerState.centerX, playerState.bottomY, playerState.z);
+ if (entityManager)
+ entityManager->reinsertSceneEntity(playerState.entity);
+ screenRect = playerState.entity->getScreenRect();
+ hasScreenRect = true;
+ depthScale = playerState.entity->getDepthScale();
+ }
+ debugC(1, kDebugPlayer,
+ "Harvester: PC_GOTO_XZ applied x=%d z=%d pos=(%d,%d,z=%.2f) screen_rect=(%d,%d)-(%d,%d) depth_scale=%.3f",
+ x, z, playerState.centerX, playerState.bottomY, (double)playerState.z,
+ hasScreenRect ? screenRect.left : 0, hasScreenRect ? screenRect.top : 0,
+ hasScreenRect ? screenRect.right : 0, hasScreenRect ? screenRect.bottom : 0,
+ (double)depthScale);
+}
+
+void Player::rebindAfterSceneRefresh(HarvesterEngine &engine, const RoomSetupState &state,
EntityManager *entityManager, bool preservePlayerPlacement) {
+ RoomPlayerState &playerState = _state;
playerState.entity = entityManager ? entityManager->findSceneEntityByName("PLAYER") : nullptr;
if (playerState.entity) {
if (!preservePlayerPlacement || playerState.facing < 0) {
@@ -1143,7 +1318,7 @@ void Player::rebindAfterSceneRefresh(const RoomSetupState &state, RoomPlayerStat
}
const int facing = playerState.facing >= 0 ? playerState.facing : state.playerFacing;
- (void)setIdleAnimation(playerState, facing);
+ (void)setIdleAnimation(facing);
(void)applyRoomActorPlacement(state, *playerState.entity,
playerState.centerX, playerState.bottomY, playerState.z);
}
@@ -1170,22 +1345,11 @@ void Player::rebindAfterSceneRefresh(const RoomSetupState &state, RoomPlayerStat
playerState.hitKnockbackDecayStep = 0;
debugC(2, kDebugPlayer, "Harvester: rebound player after scene refresh room='%s' entity=%d preserve_placement=%d",
state.roomName.c_str(), playerState.entity != nullptr, preservePlayerPlacement);
+ playerState.combatLoadout = engine.getScript() ? engine.getScript()->getPlayerCombatLoadout() : 0;
}
-void Player::syncAnimationPlacement(RoomPlayerState &playerState) {
- if (!playerState.entity)
- return;
-
- const Common::Rect rect = playerState.entity->getScreenRect();
- const int centerX = rect.left + rect.width() / 2;
- if (playerState.centerX != centerX || playerState.bottomY != rect.bottom) {
- debugC(3, kDebugPlayer,
- "Harvester: player frame bounds frame=%d base=(%d,%d) rect=(%d,%d)-(%d,%d) z=%.2f",
- playerState.entity->getCurrentFrame(), playerState.entity->getX(), playerState.entity->getY(),
- rect.left, rect.top, rect.right, rect.bottom, (double)playerState.z);
- }
- playerState.centerX = centerX;
- playerState.bottomY = rect.bottom;
+void Player::syncAnimationPlacement() {
+ syncPlayerAnimationPlacement(_state);
}
float Player::computeDepthScale(const RoomSetupState &state, float z) {
@@ -1283,33 +1447,29 @@ bool Player::isIdleAnimationExcludedRoom(const Common::String &roomName) {
return false;
}
-void Player::updateIdleTrigger(RoomIdleAnimationState &idleState) {
- idleState.triggerTick = MAX(idleState.activityTick, idleState.resetTick) + kRoomPlayerIdleDelayTicks;
-}
-void Player::setMoveTarget(const RoomSetupState &state, RoomPlayerState &playerState,
- int targetX, float targetZ) {
+void Player::setMoveTarget(const RoomSetupState &state, int targetX, float targetZ) {
+ RoomPlayerState &playerState = _state;
setMoveTargetInternal(state, playerState, targetX, targetZ,
mapRoomDepthToScreenY(state, targetZ));
}
-void Player::setRegionMoveTarget(const RoomSetupState &state, RoomPlayerState &playerState,
- int targetX, float targetZ) {
+void Player::setRegionMoveTarget(const RoomSetupState &state, int targetX, float targetZ) {
+ RoomPlayerState &playerState = _state;
setMoveTargetInternal(state, playerState, targetX, targetZ,
mapRoomDepthToScreenY(state, targetZ));
}
-void Player::setMoveTargetFromScreenPoint(const RoomSetupState &state,
- RoomPlayerState &playerState, int targetX, int targetBottomY) {
+void Player::setMoveTargetFromScreenPoint(const RoomSetupState &state, int targetX, int targetBottomY) {
+ RoomPlayerState &playerState = _state;
const int clampedTargetBottomY = clampRoomMovementY(state, targetBottomY);
setMoveTargetInternal(state, playerState, targetX,
mapRoomScreenYToDepth(state, clampedTargetBottomY), clampedTargetBottomY);
}
bool Player::resolveBlockedStartupSpawn(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState) {
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity)
return false;
@@ -1381,8 +1541,16 @@ float Player::resolveRegionTargetZ(const RegionRecord ®ion) {
return (float)(region.minZ + (region.maxZ - region.minZ) / 2);
}
-bool Player::syncCombatLoadoutVisual(HarvesterEngine &engine, const RoomSetupState &state,
- RoomPlayerState &playerState, int loadout) {
+void Player::syncCombatLoadout(HarvesterEngine &engine, const RoomSetupState &state) {
+ if (_state.entity) {
+ (void)syncCombatLoadoutVisual(engine, state, engine.getScript()->getPlayerCombatLoadout());
+ } else if (engine.getScript()) {
+ _state.combatLoadout = engine.getScript()->getPlayerCombatLoadout();
+ }
+}
+
+bool Player::syncCombatLoadoutVisual(HarvesterEngine &engine, const RoomSetupState &state, int loadout) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity)
return false;
@@ -1415,7 +1583,7 @@ bool Player::syncCombatLoadoutVisual(HarvesterEngine &engine, const RoomSetupSta
playerState.hitResumeFacing = -1;
playerState.hitKnockbackRemainingX = 0;
playerState.hitKnockbackDecayStep = 0;
- (void)setIdleAnimation(playerState, playerState.facing >= 0 ? playerState.facing : 0);
+ (void)setIdleAnimation(playerState.facing >= 0 ? playerState.facing : 0);
if (applyRoomActorPlacement(state, *playerState.entity,
playerState.centerX, playerState.bottomY, playerState.z)) {
reinsertPlayerSceneEntity(engine, playerState);
@@ -1430,32 +1598,12 @@ bool Player::syncCombatLoadoutVisual(HarvesterEngine &engine, const RoomSetupSta
return true;
}
-bool Player::setIdleAnimation(RoomPlayerState &playerState, int facing) {
- if (!playerState.entity)
- return false;
-
- const PlayerAnimationRange range = resolvePlayerAnimationRange(facing);
- const bool changed = playerState.facing != facing ||
- playerState.entity->getCurrentFrame() != range.idleFrame ||
- playerState.entity->getAnimationRate() != 0;
- playerState.facing = facing;
- playerState.nextMovementTick = 0;
- playerState.keyboardWalkRequest = -1;
- playerState.walkHorizontalDirection = 0;
- playerState.walkDepthDirection = 0;
- playerState.entity->setAnimationRate(0);
- playerState.entity->setAnimationFrameRange(range.idleFrame, range.idleFrame, false);
- playerState.entity->setCurrentFrame(range.idleFrame);
- if (changed) {
- debugC(1, kDebugPlayer,
- "Harvester: player idle animation facing=%d frame=%d",
- facing, range.idleFrame);
- }
- return changed;
+bool Player::setIdleAnimation(int facing) {
+ return setPlayerIdleAnimation(_state, facing);
}
-bool Player::startAttackAnimation(const RoomSetupState &state,
- RoomPlayerState &playerState, const Common::Point &mousePos) {
+bool Player::startAttackAnimation(const RoomSetupState &state, const Common::Point &mousePos) {
+ RoomPlayerState &playerState = _state;
PlayerAttackAnimationRange range;
if (!resolvePlayerAttackAnimationRange(state, playerState, mousePos, range))
return false;
@@ -1468,7 +1616,8 @@ bool Player::startAttackAnimation(const RoomSetupState &state,
}
bool Player::startKeyboardAttackAnimation(const RoomSetupState &state,
- RoomPlayerState &playerState, bool attackLeft, bool attackRight, bool attackUp, bool attackDown) {
+ bool attackLeft, bool attackRight, bool attackUp, bool attackDown) {
+ RoomPlayerState &playerState = _state;
(void)state;
PlayerAttackAnimationRange range;
@@ -1483,8 +1632,8 @@ bool Player::startKeyboardAttackAnimation(const RoomSetupState &state,
return true;
}
-bool Player::updateAttackAnimationState(HarvesterEngine &engine,
- RoomPlayerState &playerState) {
+bool Player::updateAttackAnimationState(HarvesterEngine &engine) {
+ RoomPlayerState &playerState = _state;
if (!playerState.attackActive || !playerState.entity)
return false;
bool changed = false;
@@ -1527,11 +1676,11 @@ bool Player::updateAttackAnimationState(HarvesterEngine &engine,
playerState.attackContactResolved = false;
playerState.attackTargetName.clear();
playerState.attackTargetClassId = -1;
- return setIdleAnimation(playerState, resumeFacing) || changed;
+ return setIdleAnimation(resumeFacing) || changed;
}
-bool Player::startHitAnimation(HarvesterEngine &engine, RoomPlayerState &playerState,
- int monsterAttackFirstFrame) {
+bool Player::startHitAnimation(HarvesterEngine &engine, int monsterAttackFirstFrame) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity || playerState.deathActive)
return false;
@@ -1577,9 +1726,8 @@ bool Player::startHitAnimation(HarvesterEngine &engine, RoomPlayerState &playerS
}
bool Player::updateHitAnimationState(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState) {
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations) {
+ RoomPlayerState &playerState = _state;
if (!playerState.hitActive || !playerState.entity)
return false;
@@ -1612,10 +1760,11 @@ bool Player::updateHitAnimationState(HarvesterEngine &engine, const RoomSetupSta
playerState.hitResumeFacing = -1;
playerState.hitKnockbackRemainingX = 0;
playerState.hitKnockbackDecayStep = 0;
- return setIdleAnimation(playerState, resumeFacing) || changed;
+ return setIdleAnimation(resumeFacing) || changed;
}
-bool Player::startDeathAnimation(RoomPlayerState &playerState, int damageType, bool goreEnabled) {
+bool Player::startDeathAnimation(int damageType, bool goreEnabled) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity || playerState.deathActive)
return false;
@@ -1666,7 +1815,8 @@ bool Player::startDeathAnimation(RoomPlayerState &playerState, int damageType, b
return true;
}
-bool Player::updateDeathAnimationState(RoomPlayerState &playerState) {
+bool Player::updateDeathAnimationState() {
+ RoomPlayerState &playerState = _state;
if (!playerState.deathActive || !playerState.entity)
return false;
@@ -1691,7 +1841,8 @@ bool Player::updateDeathAnimationState(RoomPlayerState &playerState) {
return true;
}
-bool Player::startTurnAnimation(RoomPlayerState &playerState, int targetFacing) {
+bool Player::startTurnAnimation(int targetFacing) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity || playerState.hitActive ||
playerState.facing < 0 || playerState.facing == targetFacing)
return false;
@@ -1728,7 +1879,8 @@ bool Player::startTurnAnimation(RoomPlayerState &playerState, int targetFacing)
return true;
}
-bool Player::updateTurnAnimationState(RoomPlayerState &playerState) {
+bool Player::updateTurnAnimationState() {
+ RoomPlayerState &playerState = _state;
if (!playerState.turnActive || !playerState.entity)
return false;
if (playerState.entity->getCurrentFrame() != playerState.turnEndFrame)
@@ -1749,9 +1901,9 @@ bool Player::updateTurnAnimationState(RoomPlayerState &playerState) {
}
bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState, int regionFacing) {
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations,
+ int regionFacing) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity || !playerState.hasMoveTarget || playerState.turnActive || playerState.hitActive)
return false;
@@ -1771,7 +1923,7 @@ bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state
updatePlayerMoveTargetProgress(state, playerState, regionFacing);
if (hasPlayerReachedMoveTarget(playerState)) {
playerState.hasMoveTarget = false;
- return setIdleAnimation(playerState, playerState.facing >= 0 ? playerState.facing : 0);
+ return setIdleAnimation(playerState.facing >= 0 ? playerState.facing : 0);
}
const int previousCenterX = playerState.centerX;
@@ -1808,12 +1960,12 @@ bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state
}
if (horizontalDirection == 0 && depthDirection == 0) {
playerState.hasMoveTarget = false;
- return setIdleAnimation(playerState, playerState.facing >= 0 ? playerState.facing : 0);
+ return setIdleAnimation(playerState.facing >= 0 ? playerState.facing : 0);
}
const int desiredFacing = resolveFacingFromMoveDirection(
horizontalDirection, depthDirection, playerState.facing);
if (regionFacing >= 0 && desiredFacing != playerState.facing &&
- startTurnAnimation(playerState, desiredFacing)) {
+ startTurnAnimation(desiredFacing)) {
debugC(2, kDebugPlayer,
"Harvester: player region target turn room='%s' required_facing=%d movement_facing=%d target=(%d,z=%.2f)",
state.roomName.c_str(), regionFacing, desiredFacing,
@@ -1871,9 +2023,7 @@ bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state
}
setPlayerCurrentBlocker(playerState, blocker);
if (blocker) {
- return setIdleAnimation(playerState,
- resolveFacingFromMoveDirection(horizontalDirection, depthDirection,
- playerState.facing));
+ return setIdleAnimation(resolveFacingFromMoveDirection(horizontalDirection, depthDirection, playerState.facing));
}
playerState.hasMoveTarget = false;
@@ -1884,7 +2034,7 @@ bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state
else
idleFacing = depthDirection < 0 ? 3 : 0;
}
- return setIdleAnimation(playerState, idleFacing);
+ return setIdleAnimation(idleFacing);
}
const int actualFacing = desiredFacing;
@@ -1898,7 +2048,7 @@ bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state
actualFacing, playerState.entity->getCurrentFrame(), (double)computePlayerRenderZ(playerState),
horizontalDirection, depthDirection);
}
- syncAnimationPlacement(playerState);
+ syncAnimationPlacement();
refreshPlayerCurrentBlocker(engine, sceneObjects, sceneAnimations, playerState);
if (engine.isPathfindingDebugEnabled()) {
debugC(1, kDebugPathfinding,
@@ -1917,9 +2067,9 @@ bool Player::stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state
}
bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState, bool moveLeft, bool moveRight, bool moveUp, bool moveDown) {
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations,
+ bool moveLeft, bool moveRight, bool moveUp, bool moveDown) {
+ RoomPlayerState &playerState = _state;
if (!playerState.entity || !supportsMovementBand(state))
return false;
if (playerState.turnActive || playerState.hitActive)
@@ -1948,7 +2098,7 @@ bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState
if (horizontalInput == 0 && verticalInput == 0) {
if (playerState.hasMoveTarget || playerState.facing < 0)
return false;
- return setIdleAnimation(playerState, playerState.facing);
+ return setIdleAnimation(playerState.facing);
}
const int previousBaseX = playerState.entity->getX();
@@ -1976,8 +2126,7 @@ bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState
fabsf(candidateZ - playerState.z) <= kRoomDepthCompareEpsilon) {
playerState.hasMoveTarget = false;
if (depthBoundaryReached) {
- const bool stopped = setIdleAnimation(
- playerState, playerState.facing >= 0 ? playerState.facing : 0);
+ const bool stopped = setIdleAnimation(playerState.facing >= 0 ? playerState.facing : 0);
if (stopped) {
debugC(3, kDebugPathfinding,
"Harvester: player keyboard depth boundary room='%s' input_y=%d pos=(%d,%d,z=%.2f) bounds=(%d,%d)",
@@ -1987,12 +2136,12 @@ bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState
}
return stopped;
}
- return setIdleAnimation(playerState, playerState.facing >= 0 ? playerState.facing : 0);
+ return setIdleAnimation(playerState.facing >= 0 ? playerState.facing : 0);
}
const int desiredFacing = resolveFacingFromRoomMovement(
playerState.centerX, playerState.bottomY, candidateCenterX, candidateBottomY);
- if (desiredFacing != playerState.facing && startTurnAnimation(playerState, desiredFacing)) {
+ if (desiredFacing != playerState.facing && startTurnAnimation(desiredFacing)) {
playerState.keyboardWalkRequest = -1;
return true;
}
@@ -2005,7 +2154,7 @@ bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState
playerState, candidateCenterX, candidateBottomY, candidateZ,
horizontalInput, verticalInput);
if (!moved)
- return setIdleAnimation(playerState, playerState.facing >= 0 ? playerState.facing : 0);
+ return setIdleAnimation(playerState.facing >= 0 ? playerState.facing : 0);
const int actualFacing = resolveFacingFromRoomMovement(
previousBaseX, previousBaseY, playerState.entity->getX(), playerState.entity->getY());
@@ -2019,7 +2168,7 @@ bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState
"Harvester: player keyboard walk bank restart facing=%d frame=%d",
actualFacing, playerState.entity->getCurrentFrame());
}
- syncAnimationPlacement(playerState);
+ syncAnimationPlacement();
debugC(2, kDebugPlayer,
"Harvester: player keyboard move room='%s' input=(%d,%d) step=(%d,%d) pos=(%d,%d,z=%.2f) facing=%d frame=%d moved=%d",
state.roomName.c_str(), (moveRight ? 1 : 0) - (moveLeft ? 1 : 0),
@@ -2029,8 +2178,9 @@ bool Player::stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState
return true;
}
-bool Player::requestIdleAnimationExit(const RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState) {
+bool Player::requestIdleAnimationExit(const RoomSetupState &state) {
+ RoomPlayerState &playerState = _state;
+ RoomIdleAnimationState &idleState = _idleState;
if (!idleState.active || idleState.exiting || !idleState.entity)
return false;
@@ -2051,8 +2201,9 @@ bool Player::requestIdleAnimationExit(const RoomSetupState &state,
return true;
}
-bool Player::startIdleAnimation(HarvesterEngine &engine, const RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState) {
+bool Player::startIdleAnimation(HarvesterEngine &engine, const RoomSetupState &state) {
+ RoomPlayerState &playerState = _state;
+ RoomIdleAnimationState &idleState = _idleState;
if (!playerState.entity || idleState.active || isIdleAnimationExcludedRoom(state.roomName))
return false;
@@ -2082,8 +2233,9 @@ bool Player::startIdleAnimation(HarvesterEngine &engine, const RoomSetupState &s
return true;
}
-bool Player::updateIdleAnimation(const RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState) {
+bool Player::updateIdleAnimation(const RoomSetupState &state) {
+ RoomPlayerState &playerState = _state;
+ RoomIdleAnimationState &idleState = _idleState;
if (!idleState.active || !idleState.entity)
return false;
diff --git a/engines/harvester/player.h b/engines/harvester/player.h
index 414ac7337fd..25cacd7a423 100644
--- a/engines/harvester/player.h
+++ b/engines/harvester/player.h
@@ -28,11 +28,92 @@ namespace Harvester {
class EntityManager;
+struct RoomPlayerState {
+ Entity *entity = nullptr;
+ int centerX = 0;
+ int bottomY = 0;
+ float z = 0.0f;
+ int facing = -1;
+ int combatLoadout = 0;
+ uint32 nextMovementTick = 0;
+ int keyboardWalkRequest = -1;
+ int walkHorizontalDirection = 0;
+ int walkDepthDirection = 0;
+ bool hasMoveTarget = false;
+ int targetX = 0;
+ int targetBottomY = 0;
+ float targetZ = 0.0f;
+ bool moveTargetXReached = false;
+ bool moveTargetZReached = false;
+ Common::String currentBlockerName;
+
+ Common::String upwardBlockerHistory;
+ Common::String downwardBlockerHistory;
+ Common::String leftwardBlockerHistory;
+ Common::String rightwardBlockerHistory;
+ bool turnActive = false;
+ int turnTargetFacing = -1;
+ int turnFirstFrame = -1;
+ int turnLastFrame = -1;
+ int turnEndFrame = -1;
+ bool turnPlayBackwards = false;
+ bool attackActive = false;
+ int attackFirstFrame = -1;
+ int attackLastFrame = -1;
+ int attackContactFrame = -1;
+ int attackResumeFacing = -1;
+ bool attackSoundPlayed = false;
+ int attackSoundPlaybackFrame = -1;
+ bool attackContactResolved = false;
+
+ Common::String attackTargetName;
+ int attackTargetClassId = -1;
+ bool hitActive = false;
+ int hitFirstFrame = -1;
+ int hitLastFrame = -1;
+ int hitResumeFacing = -1;
+ int hitKnockbackRemainingX = 0;
+ int hitKnockbackDecayStep = 0;
+ bool deathActive = false;
+ int deathFirstFrame = -1;
+ int deathLastFrame = -1;
+ int deathDamageType = 0;
+};
+
+struct RoomIdleAnimationState {
+ Entity *entity = nullptr;
+ int restoreFacing = -1;
+ uint32 activityTick = 0;
+ uint32 resetTick = 0;
+ uint32 triggerTick = 0;
+ bool active = false;
+ bool loopStarted = false;
+ bool exiting = false;
+};
+
class Player {
public:
- static void rebindAfterSceneRefresh(const RoomSetupState &state, RoomPlayerState &playerState,
+ Player() = default;
+ Player(const Player &) = delete;
+ Player &operator=(const Player &) = delete;
+
+ const RoomPlayerState &getState() const { return _state; }
+ const RoomIdleAnimationState &getIdleState() const { return _idleState; }
+ void initialize(const RoomSetupState &state, Entity *entity, int combatLoadout);
+ bool isCombatLocked() const;
+ void cancelMovement();
+ void cancelMovementForAttack();
+ bool cancelAttackAnimation();
+ void clearAttackTarget();
+ void captureAttackTarget(const Common::String &name, int classId);
+ void markAttackContactResolved();
+ void resetIdleState();
+ void noteActivity();
+ void cancelIdleAnimation();
+ void applyGotoXZ(const RoomSetupState &state, EntityManager *entityManager, int x, int z);
+ void rebindAfterSceneRefresh(HarvesterEngine &engine, const RoomSetupState &state,
EntityManager *entityManager, bool preservePlayerPlacement);
- static void syncAnimationPlacement(RoomPlayerState &playerState);
+ void syncAnimationPlacement();
static float computeDepthScale(const RoomSetupState &state, float z);
static int resolveFacingFrame(int facing);
static const char *describeCombatLoadout(int loadout);
@@ -45,52 +126,42 @@ public:
static bool supportsMovementBand(const RoomSetupState &state);
static uint32 getRuntimeClockTicks();
static bool isIdleAnimationExcludedRoom(const Common::String &roomName);
- static void updateIdleTrigger(RoomIdleAnimationState &idleState);
- static void setMoveTarget(const RoomSetupState &state, RoomPlayerState &playerState,
- int targetX, float targetZ);
- static void setRegionMoveTarget(const RoomSetupState &state, RoomPlayerState &playerState,
- int targetX, float targetZ);
- static void setMoveTargetFromScreenPoint(const RoomSetupState &state,
- RoomPlayerState &playerState, int targetX, int targetBottomY);
- static bool resolveBlockedStartupSpawn(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState);
+
+ void setMoveTarget(const RoomSetupState &state, int targetX, float targetZ);
+ void setRegionMoveTarget(const RoomSetupState &state, int targetX, float targetZ);
+ void setMoveTargetFromScreenPoint(const RoomSetupState &state, int targetX, int targetBottomY);
+ bool resolveBlockedStartupSpawn(HarvesterEngine &engine, const RoomSetupState &state,
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations);
static int resolveRegionTargetX(const RoomSetupState &state, const RegionRecord ®ion,
const RoomPlayerState &playerState);
static float resolveRegionTargetZ(const RegionRecord ®ion);
- static bool syncCombatLoadoutVisual(HarvesterEngine &engine, const RoomSetupState &state,
- RoomPlayerState &playerState, int loadout);
- static bool setIdleAnimation(RoomPlayerState &playerState, int facing);
- static bool startAttackAnimation(const RoomSetupState &state,
- RoomPlayerState &playerState, const Common::Point &mousePos);
- static bool startKeyboardAttackAnimation(const RoomSetupState &state,
- RoomPlayerState &playerState, bool attackLeft, bool attackRight, bool attackUp, bool attackDown);
- static bool updateAttackAnimationState(HarvesterEngine &engine, RoomPlayerState &playerState);
- static bool startHitAnimation(HarvesterEngine &engine, RoomPlayerState &playerState,
- int monsterAttackFirstFrame);
- static bool updateHitAnimationState(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState);
- static bool startDeathAnimation(RoomPlayerState &playerState, int damageType, bool goreEnabled);
- static bool updateDeathAnimationState(RoomPlayerState &playerState);
- static bool startTurnAnimation(RoomPlayerState &playerState, int targetFacing);
- static bool updateTurnAnimationState(RoomPlayerState &playerState);
- static bool stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState, int regionFacing = -1);
- static bool stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<AnimRecord> &sceneAnimations,
- RoomPlayerState &playerState, bool moveLeft, bool moveRight, bool moveUp, bool moveDown);
- static bool requestIdleAnimationExit(const RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState);
- static bool startIdleAnimation(HarvesterEngine &engine, const RoomSetupState &state,
- RoomPlayerState &playerState, RoomIdleAnimationState &idleState);
- static bool updateIdleAnimation(const RoomSetupState &state, RoomPlayerState &playerState,
- RoomIdleAnimationState &idleState);
+ void syncCombatLoadout(HarvesterEngine &engine, const RoomSetupState &state);
+ bool syncCombatLoadoutVisual(HarvesterEngine &engine, const RoomSetupState &state, int loadout);
+ bool setIdleAnimation(int facing);
+ bool startAttackAnimation(const RoomSetupState &state, const Common::Point &mousePos);
+ bool startKeyboardAttackAnimation(const RoomSetupState &state,
+ bool attackLeft, bool attackRight, bool attackUp, bool attackDown);
+ bool updateAttackAnimationState(HarvesterEngine &engine);
+ bool startHitAnimation(HarvesterEngine &engine, int monsterAttackFirstFrame);
+ bool updateHitAnimationState(HarvesterEngine &engine, const RoomSetupState &state,
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations);
+ bool startDeathAnimation(int damageType, bool goreEnabled);
+ bool updateDeathAnimationState();
+ bool startTurnAnimation(int targetFacing);
+ bool updateTurnAnimationState();
+ bool stepMoveTarget(HarvesterEngine &engine, const RoomSetupState &state,
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations,
+ int regionFacing = -1);
+ bool stepKeyboardMovement(HarvesterEngine &engine, const RoomSetupState &state,
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Array<AnimRecord> &sceneAnimations,
+ bool moveLeft, bool moveRight, bool moveUp, bool moveDown);
+ bool requestIdleAnimationExit(const RoomSetupState &state);
+ bool startIdleAnimation(HarvesterEngine &engine, const RoomSetupState &state);
+ bool updateIdleAnimation(const RoomSetupState &state);
+
+private:
+ RoomPlayerState _state;
+ RoomIdleAnimationState _idleState;
};
} // End of namespace Harvester
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index 8a3cb38e265..9ba5b049b58 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -52,58 +52,6 @@ struct SceneState {
float targetPaletteBrightness = 1.0f;
};
-struct RoomPlayerState {
- Entity *entity = nullptr;
- int centerX = 0;
- int bottomY = 0;
- float z = 0.0f;
- int facing = -1;
- int combatLoadout = 0;
- uint32 nextMovementTick = 0;
- int keyboardWalkRequest = -1;
- int walkHorizontalDirection = 0;
- int walkDepthDirection = 0;
- bool hasMoveTarget = false;
- int targetX = 0;
- int targetBottomY = 0;
- float targetZ = 0.0f;
- bool moveTargetXReached = false;
- bool moveTargetZReached = false;
- Common::String currentBlockerName;
-
- Common::String upwardBlockerHistory;
- Common::String downwardBlockerHistory;
- Common::String leftwardBlockerHistory;
- Common::String rightwardBlockerHistory;
- bool turnActive = false;
- int turnTargetFacing = -1;
- int turnFirstFrame = -1;
- int turnLastFrame = -1;
- int turnEndFrame = -1;
- bool turnPlayBackwards = false;
- bool attackActive = false;
- int attackFirstFrame = -1;
- int attackLastFrame = -1;
- int attackContactFrame = -1;
- int attackResumeFacing = -1;
- bool attackSoundPlayed = false;
- int attackSoundPlaybackFrame = -1;
- bool attackContactResolved = false;
-
- Common::String attackTargetName;
- int attackTargetClassId = -1;
- bool hitActive = false;
- int hitFirstFrame = -1;
- int hitLastFrame = -1;
- int hitResumeFacing = -1;
- int hitKnockbackRemainingX = 0;
- int hitKnockbackDecayStep = 0;
- bool deathActive = false;
- int deathFirstFrame = -1;
- int deathLastFrame = -1;
- int deathDamageType = 0;
-};
-
struct RoomHoverState {
const ObjectRecord *object = nullptr;
const NpcRecord *npc = nullptr;
@@ -113,17 +61,6 @@ struct RoomHoverState {
int cursorSequence = 7;
};
-struct RoomIdleAnimationState {
- Entity *entity = nullptr;
- int restoreFacing = -1;
- uint32 activityTick = 0;
- uint32 resetTick = 0;
- uint32 triggerTick = 0;
- bool active = false;
- bool loopStarted = false;
- bool exiting = false;
-};
-
bool sameMonsterEntityState(const MonsterRecord &lhs, const MonsterRecord &rhs);
bool applyRoomActorPlacement(const RoomSetupState &state, Entity &entity,
int centerX, int bottomY, float z, const Common::String *entranceName = nullptr);
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index 63a04825872..9e938eab48a 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -128,78 +128,57 @@ Scene::Scene(HarvesterEngine &engine, Flow &flow, SceneState &scene, EntityManag
_cheats(cheats), _view(view), _canExitCloseupToParent(canExitCloseupToParent),
_roomItems(engine, scene, _sceneRuntime, inventory, _pendingTransition.roomName),
_presentation(engine, scene, view.art, view.inspectFont, view.useNativeInspectFont),
- _interactionProcessor(engine, flow, scene, _playerState, _pendingRegionName, _pendingTransition.roomName,
+ _interactionProcessor(engine, flow, scene, _player, _pendingRegionName, _pendingTransition.roomName,
_pendingTransition.isRoomName, _pendingTransition.usesSavedRoomState, _pendingTransition.savedRoomState,
canExitCloseupToParent, *this) {
}
void Scene::resetIdleState() {
- _idleState = RoomIdleAnimationState();
- _idleState.activityTick = Player::getRuntimeClockTicks();
- _idleState.resetTick = _idleState.activityTick;
- Player::updateIdleTrigger(_idleState);
+ _player.resetIdleState();
}
void Scene::notePlayerActivity() {
- _idleState.activityTick = Player::getRuntimeClockTicks();
- Player::updateIdleTrigger(_idleState);
+ _player.noteActivity();
}
bool Scene::isPlayerCombatLocked() const {
- return _playerState.attackActive || _playerState.hitActive || _playerState.deathActive;
+ return _player.isCombatLocked();
}
bool Scene::cancelPlayerAttackAnimation() {
- if (!_playerState.attackActive)
- return false;
-
- _playerState.attackActive = false;
- _playerState.attackFirstFrame = -1;
- _playerState.attackLastFrame = -1;
- _playerState.attackContactFrame = -1;
- if (!_playerState.entity)
- return false;
- _playerState.attackSoundPlayed = false;
- _playerState.attackSoundPlaybackFrame = -1;
- _playerState.attackContactResolved = false;
- _playerState.attackTargetName.clear();
- _playerState.attackTargetClassId = -1;
- const int resumeFacing = _playerState.attackResumeFacing >= 0
- ? _playerState.attackResumeFacing
- : (_playerState.facing >= 0 ? _playerState.facing : 0);
- _playerState.attackResumeFacing = -1;
- return Player::setIdleAnimation(_playerState, resumeFacing);
+ return _player.cancelAttackAnimation();
}
void Scene::stopPlayerRegionInteraction() {
+ const RoomPlayerState &playerState = _player.getState();
_inputState.moveLeft = false;
_inputState.moveRight = false;
_inputState.moveUp = false;
_inputState.moveDown = false;
_pendingRegionName.clear();
(void)cancelPlayerAttackAnimation();
- _playerState.hasMoveTarget = false;
- _playerState.turnActive = false;
- _playerState.turnTargetFacing = -1;
- if (_playerState.entity && _playerState.facing >= 0)
- (void)Player::setIdleAnimation(_playerState, _playerState.facing);
+ _player.cancelMovement();
+ if (playerState.entity && playerState.facing >= 0)
+ (void)_player.setIdleAnimation(playerState.facing);
syncPlayerPlacement();
}
void Scene::syncPlayerPlacement() {
- Player::syncAnimationPlacement(_playerState);
+ _player.syncAnimationPlacement();
}
void Scene::captureCurrentSaveState() {
+ const RoomPlayerState &playerState = _player.getState();
syncPlayerPlacement();
_sceneRuntime.syncCurrentRoomRuntimeState(_scene.sceneRegions);
- const int facing = _playerState.facing >= 0 ? _playerState.facing : _scene.state.playerFacing;
+ const int facing = playerState.facing >= 0 ? playerState.facing : _scene.state.playerFacing;
_engine.captureCurrentSaveRoomState(_scene.state.entranceName, _scene.state.roomName,
- _playerState.centerX, _playerState.bottomY, (int)_playerState.z, facing,
+ playerState.centerX, playerState.bottomY, (int)playerState.z, facing,
_scene.state.discNumber, _engine.getMusicPath());
}
bool Scene::applyCurrentRoomRuntimeMutationsInPlace(bool preservePaletteState) {
+ const RoomPlayerState &playerState = _player.getState();
Script *script = _engine.getScript();
ResourceManager *resources = _engine.getResources();
if (!script || !resources)
@@ -234,9 +213,8 @@ bool Scene::applyCurrentRoomRuntimeMutationsInPlace(bool preservePaletteState) {
_scene.sceneRegions = updatedScene.sceneRegions;
_roomItems.hideCarriedRoomItem();
const int playerCombatLoadout = script->getPlayerCombatLoadout();
- if (_playerState.entity && _playerState.combatLoadout != playerCombatLoadout &&
- !Player::syncCombatLoadoutVisual(
- _engine, updatedState, _playerState, playerCombatLoadout)) {
+ if (playerState.entity && playerState.combatLoadout != playerCombatLoadout &&
+ !_player.syncCombatLoadoutVisual(_engine, updatedState, playerCombatLoadout)) {
return false;
}
if (preservePaletteState) {
@@ -268,9 +246,7 @@ bool Scene::refreshCurrentScene(bool preservePlayerPlacement) {
return false;
_sceneRuntime.restoreRoomMonsterAnimations();
_roomItems.hideCarriedRoomItem();
- Player::rebindAfterSceneRefresh(_scene.state, _playerState, _entityManager, preservePlayerPlacement);
- _playerState.combatLoadout =
- _engine.getScript() ? _engine.getScript()->getPlayerCombatLoadout() : 0;
+ _player.rebindAfterSceneRefresh(_engine, _scene.state, _entityManager, preservePlayerPlacement);
_combat.resetForSceneRefresh(_scene.state);
_pendingRegionName.clear();
resetIdleState();
@@ -280,20 +256,14 @@ bool Scene::refreshCurrentScene(bool preservePlayerPlacement) {
}
void Scene::initializePlayerState() {
- _playerState.entity = _entityManager ? _entityManager->findSceneEntityByName("PLAYER") : nullptr;
- _playerState.centerX = _scene.state.playerSpawnX;
- _playerState.bottomY = _scene.state.playerSpawnY;
- _playerState.z = (float)_scene.state.playerSpawnZ;
- _playerState.facing = _scene.state.playerFacing;
- _playerState.combatLoadout =
- _engine.getScript() ? _engine.getScript()->getPlayerCombatLoadout() : 0;
- _playerState.turnActive = false;
- _playerState.turnTargetFacing = -1;
+ _player.initialize(_scene.state,
+ _entityManager ? _entityManager->findSceneEntityByName("PLAYER") : nullptr,
+ _engine.getScript() ? _engine.getScript()->getPlayerCombatLoadout() : 0);
_combat.initializeCombatStates(_scene.state);
}
void Scene::syncAnimatedRoomActorPlacement() {
- Player::syncAnimationPlacement(_playerState);
+ _player.syncAnimationPlacement();
if (!_entityManager)
return;
@@ -360,31 +330,7 @@ Common::Error Scene::runRoomExitCommands() {
}
void Scene::applyPlayerGotoXZ(int x, int z) {
- _playerState.hasMoveTarget = false;
- _playerState.turnActive = false;
- _playerState.turnTargetFacing = -1;
- _playerState.centerX = x;
- _playerState.z = (float)z;
- _playerState.bottomY = mapRoomDepthToScreenYForCombat(
- _scene.state, _playerState.z, _playerState.bottomY);
- Common::Rect screenRect;
- bool hasScreenRect = false;
- float depthScale = 0.0f;
- if (_playerState.entity) {
- (void)applyRoomActorPlacement(_scene.state, *_playerState.entity,
- _playerState.centerX, _playerState.bottomY, _playerState.z);
- if (_entityManager)
- _entityManager->reinsertSceneEntity(_playerState.entity);
- screenRect = _playerState.entity->getScreenRect();
- hasScreenRect = true;
- depthScale = _playerState.entity->getDepthScale();
- }
- debugC(1, kDebugPlayer,
- "Harvester: PC_GOTO_XZ applied x=%d z=%d pos=(%d,%d,z=%.2f) screen_rect=(%d,%d)-(%d,%d) depth_scale=%.3f",
- x, z, _playerState.centerX, _playerState.bottomY, (double)_playerState.z,
- hasScreenRect ? screenRect.left : 0, hasScreenRect ? screenRect.top : 0,
- hasScreenRect ? screenRect.right : 0, hasScreenRect ? screenRect.bottom : 0,
- (double)depthScale);
+ _player.applyGotoXZ(_scene.state, _entityManager, x, z);
resetIdleState();
captureCurrentSaveState();
}
@@ -403,21 +349,13 @@ void Scene::requestPlayerGameOver(const char *reason, const Common::String &sour
}
void Scene::startPlayerDefeatSequence(const char *reason, const Common::String &sourceName, int damageType) {
- if (_flow.hasPendingMainMenuReturn() || _playerState.deathActive)
+ const RoomPlayerState &playerState = _player.getState();
+ if (_flow.hasPendingMainMenuReturn() || playerState.deathActive)
return;
- if (_idleState.entity) {
- _idleState.entity->setVisible(false);
- _idleState.entity->setAnimationRate(0);
- }
- _idleState.active = false;
- _idleState.loopStarted = false;
- _idleState.exiting = false;
- _idleState.restoreFacing = -1;
- if (_playerState.entity)
- _playerState.entity->setVisible(true);
-
- if (!Player::startDeathAnimation(_playerState, damageType, _engine.isGoreEnabled())) {
+ _player.cancelIdleAnimation();
+
+ if (!_player.startDeathAnimation(damageType, _engine.isGoreEnabled())) {
debugC(1, kDebugCombat,
"Harvester: player defeat fallback reason='%s' source='%s' damage_type=%d hp=%d",
reason ? reason : "", sourceName.c_str(), damageType,
@@ -466,6 +404,8 @@ void Scene::updateRoomInterface(bool &needsRedraw) {
}
bool Scene::drawRoomFrame(bool &needsRedraw) {
+ const RoomPlayerState &playerState = _player.getState();
+ const RoomIdleAnimationState &idleState = _player.getIdleState();
if (!needsRedraw)
return true;
@@ -478,7 +418,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
const bool roomCarryActive = _roomItems.hasCarriedRoomItem();
const bool activeCarry = inventorySelectionActive || roomCarryActive;
const bool inventoryPanelContainsMouse = _inventory.isOpen() && inventoryPanelBounds.contains(_flow._mousePos);
- const bool suppressHover = _presentationState.showingInspectText || _idleState.active || _idleState.exiting ||
+ const bool suppressHover = _presentationState.showingInspectText || idleState.active || idleState.exiting ||
isPlayerCombatLocked() ||
(_inventory.isOpen() && (inventoryPanelContainsMouse || !inventorySelectionActive));
RoomHoverState hoverState = suppressHover
@@ -491,7 +431,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
const Entity *target = suppressHover ? nullptr : _roomItems.findSelectedItemTarget(_flow._mousePos, false);
if (!target)
return Common::String();
- if (target == _playerState.entity)
+ if (target == playerState.entity)
return Common::String(kPlayerInventoryLabel);
if (const ObjectRecord *object = findSceneObjectByName(_scene.sceneObjects, target->getName()))
return _engine.getScript()->resolveObjectLabel(*object);
@@ -539,7 +479,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
_presentationState.currentInteractionPromptText = promptText;
if (Entity *cursor = _entityManager ? _entityManager->getCursorEntity() : nullptr) {
cursor->setAnimationSequence(
- (_presentationState.showingInspectText || _idleState.active || _idleState.exiting ||
+ (_presentationState.showingInspectText || idleState.active || idleState.exiting ||
isPlayerCombatLocked() ||
_inventory.isOpen() || activeCarry)
? 7
@@ -548,7 +488,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
_combatEffects.drawCombatDamagePopups(*activeScreen, _engine.isCombatDebugEnabled());
- if (_engine.getScript() && _playerState.entity) {
+ if (_engine.getScript() && playerState.entity) {
drawCombatLoadoutResourceIcons(*activeScreen, *_view.art, *_engine.getScript(),
_engine.getScript()->getPlayerCombatLoadout());
}
@@ -599,13 +539,14 @@ InputResult Scene::pollRoomEvents(Input &input, bool &needsRedraw) {
}
Scene::PlayerControlState Scene::preparePlayerControlState() {
+ const RoomPlayerState &playerState = _player.getState();
Script *script = _engine.getScript();
const bool playerAlive = script && script->getPlayerCurrentHitPoints() > 0;
const bool playerControlPaused = script && script->isPlayerControlPaused();
const bool playerCanAct = playerAlive && !playerControlPaused;
if (!playerAlive && (_inputState.moveLeft || _inputState.moveRight || _inputState.moveUp || _inputState.moveDown ||
- _playerState.hasMoveTarget || _playerState.turnActive ||
- _playerState.attackActive || _playerState.hitActive)) {
+ playerState.hasMoveTarget || playerState.turnActive ||
+ playerState.attackActive || playerState.hitActive)) {
_inputState.attackModifierHeld = false;
stopPlayerRegionInteraction();
}
@@ -624,77 +565,76 @@ void Scene::advanceRuntimeEntities(bool &needsRedraw) {
}
void Scene::updatePlayerCombatAnimations(bool &needsRedraw) {
- if (Player::updateAttackAnimationState(_engine, _playerState))
+ if (_player.updateAttackAnimationState(_engine))
needsRedraw = true;
- if (Player::updateHitAnimationState(
- _engine, _scene.state, _scene.sceneObjects, _scene.sceneAnimations, _playerState)) {
+ if (_player.updateHitAnimationState(_engine, _scene.state, _scene.sceneObjects, _scene.sceneAnimations)) {
needsRedraw = true;
}
}
void Scene::updatePlayerControls(const PlayerControlState &control, bool &needsRedraw) {
+ const RoomPlayerState &playerState = _player.getState();
+ const RoomIdleAnimationState &idleState = _player.getIdleState();
const bool keyboardAttackRequested =
_inputState.attackModifierHeld && (_inputState.moveLeft || _inputState.moveRight || _inputState.moveUp || _inputState.moveDown);
if (control.canAct &&
- !_playerState.attackActive && !_playerState.hitActive && keyboardAttackRequested &&
- !_idleState.active && !_idleState.exiting) {
+ !playerState.attackActive && !playerState.hitActive && keyboardAttackRequested &&
+ !idleState.active && !idleState.exiting) {
const uint32 now = Player::getRuntimeClockTicks();
if (_inputState.nextKeyboardAttackAllowedTick == 0 || (int32)(now - _inputState.nextKeyboardAttackAllowedTick) >= 0) {
- _combat.capturePlayerAttackTargetForKeyboard(_scene.state, _playerState, _entityManager, _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown);
- if (Player::startKeyboardAttackAnimation(
- _scene.state, _playerState, _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown)) {
+ _combat.capturePlayerAttackTargetForKeyboard(_scene.state, _player, _entityManager,
+ _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown);
+ if (_player.startKeyboardAttackAnimation(_scene.state,
+ _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown)) {
_inputState.nextKeyboardAttackAllowedTick = now + kNativeKeyboardAttackRepeatTicks;
notePlayerActivity();
debugC(1, kDebugCombat,
"Harvester: _combat player keyboard attack start loadout=%d weapon='%s' damage=%d damage_type='%s' target_class='%s' target='%s' input=(L=%d R=%d U=%d D=%d) facing=%d",
- _playerState.combatLoadout,
- Player::describeCombatLoadout(_playerState.combatLoadout),
- Player::resolveCombatLoadoutDamageAmount(_playerState.combatLoadout),
- Player::describeCombatDamageType(Player::resolveCombatLoadoutDamageType(_playerState.combatLoadout)),
- describeCombatTargetClass(_playerState.attackTargetClassId),
- _playerState.attackTargetName.c_str(),
- _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown, _playerState.facing);
+ playerState.combatLoadout,
+ Player::describeCombatLoadout(playerState.combatLoadout),
+ Player::resolveCombatLoadoutDamageAmount(playerState.combatLoadout),
+ Player::describeCombatDamageType(Player::resolveCombatLoadoutDamageType(playerState.combatLoadout)),
+ describeCombatTargetClass(playerState.attackTargetClassId),
+ playerState.attackTargetName.c_str(),
+ _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown, playerState.facing);
needsRedraw = true;
} else {
- _playerState.attackTargetName.clear();
- _playerState.attackTargetClassId = -1;
+ _player.clearAttackTarget();
}
}
}
- if (control.canAct && !_playerState.attackActive && !_playerState.hitActive &&
- Player::updateTurnAnimationState(_playerState)) {
+ if (control.canAct && !playerState.attackActive && !playerState.hitActive &&
+ _player.updateTurnAnimationState()) {
needsRedraw = true;
}
if (control.canAct &&
- !_playerState.attackActive && !_playerState.hitActive &&
- !keyboardAttackRequested && !_idleState.active && !_idleState.exiting) {
+ !playerState.attackActive && !playerState.hitActive &&
+ !keyboardAttackRequested && !idleState.active && !idleState.exiting) {
const int regionFacing = _interactionProcessor.getPendingRegionFacing();
- if (Player::stepKeyboardMovement(_engine, _scene.state, _scene.sceneObjects, _scene.sceneAnimations,
- _playerState, _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown)) {
+ if (_player.stepKeyboardMovement(_engine, _scene.state, _scene.sceneObjects, _scene.sceneAnimations,
+ _inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown)) {
notePlayerActivity();
needsRedraw = true;
- } else if (Player::stepMoveTarget(
- _engine, _scene.state, _scene.sceneObjects, _scene.sceneAnimations,
- _playerState, regionFacing)) {
+ } else if (_player.stepMoveTarget(_engine, _scene.state, _scene.sceneObjects, _scene.sceneAnimations, regionFacing)) {
notePlayerActivity();
needsRedraw = true;
}
if (!_presentationState.showingInspectText && !keyboardAttackRequested &&
!_inputState.moveLeft && !_inputState.moveRight && !_inputState.moveUp && !_inputState.moveDown &&
- !_playerState.hasMoveTarget && !_playerState.turnActive && !_playerState.hitActive &&
- _playerState.entity && _playerState.facing >= 0 &&
+ !playerState.hasMoveTarget && !playerState.turnActive && !playerState.hitActive &&
+ playerState.entity && playerState.facing >= 0 &&
!Player::isIdleAnimationExcludedRoom(_scene.state.roomName) &&
- Player::getRuntimeClockTicks() > _idleState.triggerTick &&
- Player::startIdleAnimation(_engine, _scene.state, _playerState, _idleState)) {
+ Player::getRuntimeClockTicks() > idleState.triggerTick &&
+ _player.startIdleAnimation(_engine, _scene.state)) {
needsRedraw = true;
}
}
}
void Scene::updatePlayerDeath(bool &needsRedraw) {
- if (Player::updateDeathAnimationState(_playerState)) {
+ if (_player.updateDeathAnimationState()) {
requestPlayerGameOver("combat_player_death_complete", Common::String());
needsRedraw = true;
}
@@ -924,13 +864,13 @@ Common::Error Scene::tryActivatePassiveRegion(bool &needsRedraw) {
}
Common::Error Scene::resolvePlayerAttackContact(bool &needsRedraw) {
- return _combat.resolvePlayerAttackContact(_engine, _scene.state, _playerState, _entityManager,
+ return _combat.resolvePlayerAttackContact(_engine, _scene.state, _player, _entityManager,
_sceneRuntime, _combatEffects, _interactionProcessor, needsRedraw);
}
Common::Error Scene::updateRoomMonsterCombat(bool &needsRedraw) {
- return _combat.updateRoomMonsterCombat(_engine, _scene.state, _playerState, _idleState,
- _entityManager, _sceneRuntime, _combatEffects, _cheats, *this, _interactionProcessor, needsRedraw);
+ return _combat.updateRoomMonsterCombat(_engine, _scene.state, _player, _entityManager,
+ _sceneRuntime, _combatEffects, _cheats, *this, _interactionProcessor, needsRedraw);
}
void Scene::syncCombatHitEffects(bool &needsRedraw) {
@@ -939,16 +879,16 @@ void Scene::syncCombatHitEffects(bool &needsRedraw) {
}
void Scene::updateIdleAnimation(bool &needsRedraw) {
- if (Player::updateIdleAnimation(_scene.state, _playerState, _idleState))
+ if (_player.updateIdleAnimation(_scene.state))
needsRedraw = true;
}
void Scene::capturePlayerAttackTarget(const Common::Point &mousePos, const NpcRecord *npc) {
- _combat.capturePlayerAttackTarget(_scene.state, _playerState, _entityManager, mousePos, npc);
+ _combat.capturePlayerAttackTarget(_scene.state, _player, _entityManager, mousePos, npc);
}
Common::Error Scene::killDebugActiveMonster(const Common::Point &mousePos, bool &needsRedraw) {
- return _combat.killDebugActiveMonster(_engine, _scene.state, _playerState, _entityManager,
+ return _combat.killDebugActiveMonster(_engine, _scene.state, _player, _entityManager,
mousePos, _combatEffects, _interactionProcessor, needsRedraw);
}
diff --git a/engines/harvester/scene.h b/engines/harvester/scene.h
index 8c896f14bf7..733a276743e 100644
--- a/engines/harvester/scene.h
+++ b/engines/harvester/scene.h
@@ -26,6 +26,7 @@
#include "common/str.h"
#include "harvester/combat.h"
#include "harvester/input.h"
+#include "harvester/player.h"
#include "harvester/interaction.h"
#include "harvester/room_presentation.h"
#include "harvester/scene_entities.h"
@@ -63,8 +64,7 @@ public:
Scene(HarvesterEngine &engine, Flow &flow, SceneState &scene, EntityManager *entityManager,
InventorySystem &inventory, CheatSystem &cheats, const RoomViewResources &view, bool canExitCloseupToParent);
- RoomPlayerState &getPlayerState() { return _playerState; }
- RoomIdleAnimationState &getIdleState() { return _idleState; }
+ Player &getPlayer() { return _player; }
InputState &getInputState() { return _inputState; }
void initializePlayerState();
@@ -125,10 +125,9 @@ private:
EntityManager *_entityManager;
InventorySystem &_inventory;
SceneEntities _sceneRuntime;
- RoomPlayerState _playerState;
+ Player _player;
Combat _combat;
CombatEffects _combatEffects;
- RoomIdleAnimationState _idleState;
InputState _inputState;
Common::String _pendingRegionName;
CheatSystem &_cheats;
Commit: 852752b9533ad50e34006aac0083b64e74a46457
https://github.com/scummvm/scummvm/commit/852752b9533ad50e34006aac0083b64e74a46457
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:06-04:00
Commit Message:
HARVESTER: improve Combat design
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/combat.cpp
engines/harvester/combat.h
engines/harvester/scene.cpp
engines/harvester/scene.h
diff --git a/engines/harvester/combat.cpp b/engines/harvester/combat.cpp
index ee6e1325fa4..8c59eb59662 100644
--- a/engines/harvester/combat.cpp
+++ b/engines/harvester/combat.cpp
@@ -597,15 +597,23 @@ const char *describeCombatTargetClass(int classId) {
}
}
-MonsterRecord *Combat::findMonsterTargetAtPoint(RoomSetupState &state, EntityManager *entityManager, const Common::Point &point) const {
+Combat::Combat(HarvesterEngine &engine, SceneState &scene, Player &player,
+ EntityManager *entityManager, SceneEntities &sceneRuntime, CombatEffects &combatEffects,
+ const CheatSystem &cheats, InteractionCallbacks &callbacks, Interaction &interactionProcessor)
+ : _engine(engine), _scene(scene), _player(player), _entityManager(entityManager),
+ _sceneRuntime(sceneRuntime), _combatEffects(combatEffects), _cheats(cheats),
+ _callbacks(callbacks), _interactionProcessor(interactionProcessor) {
+}
+
+MonsterRecord *Combat::findMonsterTargetAtPoint(const Common::Point &point) const {
MonsterRecord *bestMonster = nullptr;
int bestZ = -0x7fffffff;
int bestTop = -0x7fffffff;
- for (MonsterRecord &monster : state.roomMonsters) {
+ for (MonsterRecord &monster : _scene.state.roomMonsters) {
if (!monster.active || !monster.visible || monster.currentHitPoints <= 0)
continue;
- Entity *entity = findSceneRuntimeEntity(entityManager, monster.monsterName);
+ Entity *entity = findSceneRuntimeEntity(_entityManager, monster.monsterName);
if (!entity || !entity->isVisible())
continue;
@@ -624,17 +632,17 @@ MonsterRecord *Combat::findMonsterTargetAtPoint(RoomSetupState &state, EntityMan
return bestMonster;
}
-MonsterRecord *Combat::findOverlappingMonsterTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager) const {
+MonsterRecord *Combat::findOverlappingMonsterTarget() const {
+ const RoomPlayerState &playerState = _player.getState();
if (!playerState.entity)
return nullptr;
- for (MonsterRecord &monster : state.roomMonsters) {
+ for (MonsterRecord &monster : _scene.state.roomMonsters) {
if (!monster.active || !monster.visible || monster.currentHitPoints <= 0)
continue;
- Entity *entity = findSceneRuntimeEntity(entityManager, monster.monsterName);
- if (entity && areCombatantsWithinRoomCombatReach(state,
+ Entity *entity = findSceneRuntimeEntity(_entityManager, monster.monsterName);
+ if (entity && areCombatantsWithinRoomCombatReach(_scene.state,
*playerState.entity, playerState.z, *entity, (float)monster.posZ, monster.engageDistance))
return &monster;
}
@@ -642,16 +650,17 @@ MonsterRecord *Combat::findOverlappingMonsterTarget(RoomSetupState &state, const
return nullptr;
}
-NpcRecord *Combat::findOverlappingNpcTarget(RoomSetupState &state, const RoomPlayerState &playerState, EntityManager *entityManager) const {
+NpcRecord *Combat::findOverlappingNpcTarget() const {
+ const RoomPlayerState &playerState = _player.getState();
if (!playerState.entity)
return nullptr;
- for (NpcRecord &npc : state.roomNpcs) {
+ for (NpcRecord &npc : _scene.state.roomNpcs) {
if (!npc.visible || npc.deathOrMonsterfyFlag || npc.deathDamageType != 0)
continue;
- Entity *entity = findSceneRuntimeEntity(entityManager, npc.npcName);
- if (entity && areCombatantsWithinRoomCombatReach(state,
+ Entity *entity = findSceneRuntimeEntity(_entityManager, npc.npcName);
+ if (entity && areCombatantsWithinRoomCombatReach(_scene.state,
*playerState.entity, playerState.z, *entity, entity->getZ(), 0))
return &npc;
}
@@ -659,19 +668,19 @@ NpcRecord *Combat::findOverlappingNpcTarget(RoomSetupState &state, const RoomPla
return nullptr;
}
-bool Combat::playerAttackCanReachTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- Entity *targetEntity, int engageDistance) const {
+bool Combat::playerAttackCanReachTarget(Entity *targetEntity, int engageDistance) const {
+ const RoomPlayerState &playerState = _player.getState();
if (!playerState.entity || !targetEntity)
return false;
if (Player::isProjectileCombatLoadout(playerState.combatLoadout))
return true;
- return areCombatantsWithinRoomCombatReach(state,
+ return areCombatantsWithinRoomCombatReach(_scene.state,
*playerState.entity, playerState.z, *targetEntity, targetEntity->getZ(), engageDistance);
}
-MonsterRecord *Combat::findProjectileContactMonsterTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager) const {
+MonsterRecord *Combat::findProjectileContactMonsterTarget() const {
+ const RoomPlayerState &playerState = _player.getState();
if (!playerState.entity)
return nullptr;
@@ -688,11 +697,11 @@ MonsterRecord *Combat::findProjectileContactMonsterTarget(RoomSetupState &state,
Entity *bestEntity = nullptr;
int bestLeadingEdge = attackSide == kNativeAttackSideLeft ? -0x7fffffff : 0x7fffffff;
- for (MonsterRecord &monster : state.roomMonsters) {
+ for (MonsterRecord &monster : _scene.state.roomMonsters) {
if (!monster.active || !monster.visible || monster.currentHitPoints <= 0)
continue;
- Entity *entity = findSceneRuntimeEntity(entityManager, monster.monsterName);
+ Entity *entity = findSceneRuntimeEntity(_entityManager, monster.monsterName);
if (!entity || !entity->isVisible() ||
!doRuntimeEntityDepthExtentsOverlap(*playerState.entity, *entity)) {
continue;
@@ -737,10 +746,9 @@ MonsterRecord *Combat::findProjectileContactMonsterTarget(RoomSetupState &state,
return bestMonster;
}
-void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player &player,
- EntityManager *entityManager, bool attackLeft, bool attackRight, bool attackUp, bool attackDown) const {
- const RoomPlayerState &playerState = player.getState();
- player.clearAttackTarget();
+void Combat::capturePlayerAttackTargetForKeyboard(bool attackLeft, bool attackRight, bool attackUp, bool attackDown) const {
+ const RoomPlayerState &playerState = _player.getState();
+ _player.clearAttackTarget();
if (!playerState.entity)
return;
@@ -820,15 +828,15 @@ void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player
bestLeadingEdge = targetLeft;
};
- for (NpcRecord &npc : state.roomNpcs) {
+ for (NpcRecord &npc : _scene.state.roomNpcs) {
if (!npc.visible || npc.deathOrMonsterfyFlag || npc.deathDamageType != 0)
continue;
- considerTarget(findSceneRuntimeEntity(entityManager, npc.npcName), npc.npcName, kEntityClassNpc);
+ considerTarget(findSceneRuntimeEntity(_entityManager, npc.npcName), npc.npcName, kEntityClassNpc);
}
- for (MonsterRecord &monster : state.roomMonsters) {
+ for (MonsterRecord &monster : _scene.state.roomMonsters) {
if (!monster.active || !monster.visible || monster.currentHitPoints <= 0)
continue;
- considerTarget(findSceneRuntimeEntity(entityManager, monster.monsterName), monster.monsterName, kEntityClassMonster);
+ considerTarget(findSceneRuntimeEntity(_entityManager, monster.monsterName), monster.monsterName, kEntityClassMonster);
}
if (!bestEntity) {
@@ -838,7 +846,7 @@ void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player
return;
}
- player.captureAttackTarget(bestName, bestClassId);
+ _player.captureAttackTarget(bestName, bestClassId);
debugC(1, kDebugCombat,
"Harvester: combat player keyboard target capture class='%s' name='%s' input=(L=%d R=%d U=%d D=%d) facing=%d target_rect=(%d,%d)-(%d,%d)",
describeCombatTargetClass(bestClassId), bestName.c_str(),
@@ -847,24 +855,24 @@ void Combat::capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player
bestEntity->getScreenRect().right, bestEntity->getScreenRect().bottom);
}
-MonsterRecord *Combat::resolveKillTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager, const Common::Point &mousePos) const {
+MonsterRecord *Combat::resolveKillTarget(const Common::Point &mousePos) const {
+ const RoomPlayerState &playerState = _player.getState();
if (playerState.attackTargetClassId == kEntityClassMonster) {
- MonsterRecord *monster = findRoomMonsterRecordByName(state, playerState.attackTargetName);
- if (isKillableMonster(monster) && selectMonsterEntity(entityManager, *monster))
+ MonsterRecord *monster = findRoomMonsterRecordByName(_scene.state, playerState.attackTargetName);
+ if (isKillableMonster(monster) && selectMonsterEntity(_entityManager, *monster))
return monster;
}
- if (MonsterRecord *monster = findMonsterTargetAtPoint(state, entityManager, mousePos)) {
- if (isKillableMonster(monster) && selectMonsterEntity(entityManager, *monster))
+ if (MonsterRecord *monster = findMonsterTargetAtPoint(mousePos)) {
+ if (isKillableMonster(monster) && selectMonsterEntity(_entityManager, *monster))
return monster;
}
if (playerState.entity) {
- for (uint i = 0; i < state.roomMonsters.size() && i < _monsterCombatStates.size(); ++i) {
- MonsterRecord &monster = state.roomMonsters[i];
+ for (uint i = 0; i < _scene.state.roomMonsters.size() && i < _monsterCombatStates.size(); ++i) {
+ MonsterRecord &monster = _scene.state.roomMonsters[i];
const MonsterCombatState &combatState = _monsterCombatStates[i];
- if (!combatState.attackActive || !isKillableMonster(&monster) || !selectMonsterEntity(entityManager, monster))
+ if (!combatState.attackActive || !isKillableMonster(&monster) || !selectMonsterEntity(_entityManager, monster))
continue;
if (!combatState.attackTargetName.empty() &&
playerState.entity->getName().equalsIgnoreCase(combatState.attackTargetName)) {
@@ -880,11 +888,11 @@ MonsterRecord *Combat::resolveKillTarget(RoomSetupState &state, const RoomPlayer
const int playerCenterX = playerRect.left + playerRect.width() / 2;
MonsterRecord *bestMonster = nullptr;
int bestScore = 0x7fffffff;
- for (MonsterRecord &monster : state.roomMonsters) {
+ for (MonsterRecord &monster : _scene.state.roomMonsters) {
if (!isKillableMonster(&monster))
continue;
- Entity *entity = selectMonsterEntity(entityManager, monster);
+ Entity *entity = selectMonsterEntity(_entityManager, monster);
if (!entity)
continue;
@@ -901,19 +909,18 @@ MonsterRecord *Combat::resolveKillTarget(RoomSetupState &state, const RoomPlayer
return bestMonster;
}
-void Combat::capturePlayerAttackTarget(RoomSetupState &state, Player &player,
- EntityManager *entityManager, const Common::Point &mousePos, const NpcRecord *hoverNpc) const {
- const RoomPlayerState &playerState = player.getState();
+void Combat::capturePlayerAttackTarget(const Common::Point &mousePos, const NpcRecord *hoverNpc) const {
+ const RoomPlayerState &playerState = _player.getState();
if (hoverNpc) {
- player.captureAttackTarget(hoverNpc->npcName, kEntityClassNpc);
+ _player.captureAttackTarget(hoverNpc->npcName, kEntityClassNpc);
debugC(1, kDebugCombat,
"Harvester: combat player target capture class='npc' name='%s' cursor=(%d,%d)",
playerState.attackTargetName.c_str(), mousePos.x, mousePos.y);
return;
}
- if (MonsterRecord *monster = findMonsterTargetAtPoint(state, entityManager, mousePos)) {
- player.captureAttackTarget(monster->monsterName, kEntityClassMonster);
+ if (MonsterRecord *monster = findMonsterTargetAtPoint(mousePos)) {
+ _player.captureAttackTarget(monster->monsterName, kEntityClassMonster);
debugC(1, kDebugCombat,
"Harvester: combat player target capture class='monster' name='%s' cursor=(%d,%d)",
playerState.attackTargetName.c_str(), mousePos.x, mousePos.y);
@@ -925,62 +932,59 @@ void Combat::capturePlayerAttackTarget(RoomSetupState &state, Player &player,
mousePos.x, mousePos.y);
}
-void Combat::captureOverlappingNpcAttackTarget(RoomSetupState &state, Player &player, EntityManager *entityManager) const {
- const RoomPlayerState &playerState = player.getState();
+void Combat::captureOverlappingNpcAttackTarget() const {
+ const RoomPlayerState &playerState = _player.getState();
if (playerState.attackTargetClassId < 0 && !Player::isProjectileCombatLoadout(playerState.combatLoadout)) {
- if (NpcRecord *fallbackNpc = findOverlappingNpcTarget(state, playerState, entityManager)) {
- player.captureAttackTarget(fallbackNpc->npcName, kEntityClassNpc);
+ if (NpcRecord *fallbackNpc = findOverlappingNpcTarget()) {
+ _player.captureAttackTarget(fallbackNpc->npcName, kEntityClassNpc);
}
}
}
-NpcRecord *Combat::selectNpcAttackContactTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager, Entity *&npcEntity) const {
- NpcRecord *npc = findRoomNpcRecordByName(state, playerState.attackTargetName);
- npcEntity = npc ? findSceneRuntimeEntity(entityManager, npc->npcName) : nullptr;
- if (!npc || !npcEntity || !playerAttackCanReachTarget(state, playerState, npcEntity))
- npc = Player::isProjectileCombatLoadout(playerState.combatLoadout) ? nullptr : findOverlappingNpcTarget(state, playerState, entityManager);
- npcEntity = npc ? findSceneRuntimeEntity(entityManager, npc->npcName) : nullptr;
+NpcRecord *Combat::selectNpcAttackContactTarget(Entity *&npcEntity) const {
+ const RoomPlayerState &playerState = _player.getState();
+ NpcRecord *npc = findRoomNpcRecordByName(_scene.state, playerState.attackTargetName);
+ npcEntity = npc ? findSceneRuntimeEntity(_entityManager, npc->npcName) : nullptr;
+ if (!npc || !npcEntity || !playerAttackCanReachTarget(npcEntity))
+ npc = Player::isProjectileCombatLoadout(playerState.combatLoadout) ? nullptr : findOverlappingNpcTarget();
+ npcEntity = npc ? findSceneRuntimeEntity(_entityManager, npc->npcName) : nullptr;
return npc;
}
-MonsterRecord *Combat::selectMonsterAttackContactTarget(RoomSetupState &state, Player &player,
- EntityManager *entityManager, Entity *&monsterEntity) const {
- const RoomPlayerState &playerState = player.getState();
+MonsterRecord *Combat::selectMonsterAttackContactTarget(Entity *&monsterEntity) const {
+ const RoomPlayerState &playerState = _player.getState();
MonsterRecord *monster = nullptr;
if (playerState.attackTargetClassId == kEntityClassMonster)
- monster = findRoomMonsterRecordByName(state, playerState.attackTargetName);
- monsterEntity = monster ? findSceneRuntimeEntity(entityManager, monster->monsterName) : nullptr;
- if (!monster || !monsterEntity || !playerAttackCanReachTarget(state, playerState, monsterEntity, monster->engageDistance)) {
+ monster = findRoomMonsterRecordByName(_scene.state, playerState.attackTargetName);
+ monsterEntity = monster ? findSceneRuntimeEntity(_entityManager, monster->monsterName) : nullptr;
+ if (!monster || !monsterEntity || !playerAttackCanReachTarget(monsterEntity, monster->engageDistance)) {
if (!Player::isProjectileCombatLoadout(playerState.combatLoadout)) {
- monster = findOverlappingMonsterTarget(state, playerState, entityManager);
+ monster = findOverlappingMonsterTarget();
} else if (playerState.attackTargetClassId < 0) {
- monster = findProjectileContactMonsterTarget(state, playerState, entityManager);
+ monster = findProjectileContactMonsterTarget();
if (monster) {
- player.captureAttackTarget(monster->monsterName, kEntityClassMonster);
+ _player.captureAttackTarget(monster->monsterName, kEntityClassMonster);
}
} else {
monster = nullptr;
}
- monsterEntity = monster ? findSceneRuntimeEntity(entityManager, monster->monsterName) : nullptr;
+ monsterEntity = monster ? findSceneRuntimeEntity(_entityManager, monster->monsterName) : nullptr;
}
return monster;
}
-NpcCombatUpdateResult Combat::updateRoomNpcCombat(HarvesterEngine &engine, RoomSetupState &state,
- EntityManager *entityManager, SceneEntities &sceneRuntime,
- Interaction &interactionProcessor, bool &needsRedraw) {
+NpcCombatUpdateResult Combat::updateRoomNpcCombat(bool &needsRedraw) {
NpcCombatUpdateResult result;
- for (uint i = 0; i < state.roomNpcs.size(); ++i) {
- NpcRecord &npc = state.roomNpcs[i];
+ for (uint i = 0; i < _scene.state.roomNpcs.size(); ++i) {
+ NpcRecord &npc = _scene.state.roomNpcs[i];
NpcCombatState &combatState = _npcCombatStates[i];
- Entity *entity = findSceneRuntimeEntity(entityManager, npc.npcName);
+ Entity *entity = findSceneRuntimeEntity(_entityManager, npc.npcName);
if (!entity || !npc.visible || npc.deathOrMonsterfyFlag) {
clearRoomNpcCombatState(combatState);
continue;
}
if (!combatState.deathActive && npc.active && npc.deathDamageType != 0) {
- if (beginNpcDeathTransition(engine, npc, *entity, combatState, npc.deathDamageType, needsRedraw))
+ if (beginNpcDeathTransition(npc, *entity, combatState, npc.deathDamageType, needsRedraw))
continue;
debugC(1, kDebugCombat,
@@ -989,7 +993,7 @@ NpcCombatUpdateResult Combat::updateRoomNpcCombat(HarvesterEngine &engine, RoomS
combatState.deathDamageType = npc.deathDamageType;
combatState.deathLastFrame = entity->getCurrentFrame();
result.finalizedDeath = true;
- result.error = finalizeNpcDeathTransition(engine, entityManager, sceneRuntime, npc, combatState, interactionProcessor, needsRedraw);
+ result.error = finalizeNpcDeathTransition(npc, combatState, needsRedraw);
return result;
}
if (!combatState.deathActive)
@@ -1002,21 +1006,21 @@ NpcCombatUpdateResult Combat::updateRoomNpcCombat(HarvesterEngine &engine, RoomS
entity->setCurrentFrame(combatState.deathLastFrame);
entity->setAnimationEnabled(false);
result.finalizedDeath = true;
- result.error = finalizeNpcDeathTransition(engine, entityManager, sceneRuntime, npc, combatState, interactionProcessor, needsRedraw);
+ result.error = finalizeNpcDeathTransition(npc, combatState, needsRedraw);
return result;
}
return result;
}
-bool Combat::queueInnerSanctumHerrillDeathAfterMuck(HarvesterEngine &engine, RoomSetupState &state, const MonsterRecord &monster) const {
+bool Combat::queueInnerSanctumHerrillDeathAfterMuck(const MonsterRecord &monster) const {
if (!monster.roomName.equalsIgnoreCase(kInnerSanctumRoomName) ||
!monster.monsterName.equalsIgnoreCase(kMuckeyMonsterName) ||
!monster.onDeathActionTag.equalsIgnoreCase(kActivateInnerSanctumDoorActionTag)) {
return false;
}
- Script *script = engine.getScript();
- NpcRecord *herrill = findRoomNpcRecordByName(state, kHerrillLogNpcName);
+ Script *script = _engine.getScript();
+ NpcRecord *herrill = findRoomNpcRecordByName(_scene.state, kHerrillLogNpcName);
if (!script || !herrill || !herrill->visible ||
herrill->deathOrMonsterfyFlag || herrill->deathDamageType != 0) {
return false;
@@ -1037,11 +1041,11 @@ bool Combat::queueInnerSanctumHerrillDeathAfterMuck(HarvesterEngine &engine, Roo
return true;
}
-bool Combat::beginNpcDeathTransition(HarvesterEngine &engine,
- NpcRecord &npc, Entity &npcEntity, NpcCombatState &combatState, int deathDamageType, bool &needsRedraw) const {
+bool Combat::beginNpcDeathTransition(NpcRecord &npc, Entity &npcEntity, NpcCombatState &combatState,
+ int deathDamageType, bool &needsRedraw) const {
DeathAnimationRange deathRange;
if (!resolveNpcDeathAnimationRange(npcEntity, !npc.monsterfyTargetName.empty(),
- deathDamageType, engine.isGoreEnabled(), deathRange))
+ deathDamageType, _engine.isGoreEnabled(), deathRange))
return false;
combatState.deathActive = true;
@@ -1054,7 +1058,7 @@ bool Combat::beginNpcDeathTransition(HarvesterEngine &engine,
npcEntity.setAnimationEnabled(true);
npcEntity.setCurrentFrame(deathRange.firstFrame);
if (!npc.audioPath.empty())
- (void)engine.playSound(npc.audioPath);
+ (void)_engine.playSound(npc.audioPath);
debugC(1, kDebugCombat,
"Harvester: combat npc death start target='%s' damage_type=%d frames=%d..%d monsterfy='%s' on_death='%s'",
npc.npcName.c_str(), deathDamageType, deathRange.firstFrame, deathRange.lastFrame,
@@ -1063,11 +1067,9 @@ bool Combat::beginNpcDeathTransition(HarvesterEngine &engine,
return true;
}
-Common::Error Combat::finalizeNpcDeathTransition(HarvesterEngine &engine,
- EntityManager *entityManager, SceneEntities &sceneRuntime, NpcRecord &npc, NpcCombatState &combatState,
- Interaction &interactionProcessor, bool &needsRedraw) const {
- Script *script = engine.getScript();
- Entity *npcEntity = findSceneRuntimeEntity(entityManager, npc.npcName);
+Common::Error Combat::finalizeNpcDeathTransition(NpcRecord &npc, NpcCombatState &combatState, bool &needsRedraw) const {
+ Script *script = _engine.getScript();
+ Entity *npcEntity = findSceneRuntimeEntity(_entityManager, npc.npcName);
// Native state 0x35 leaves non-monsterfied NPCs as a dead state-0x38 actor
// in the current room, while the NpcRecord death flag suppresses later setup.
const bool retainDeathEntity =
@@ -1085,7 +1087,7 @@ Common::Error Combat::finalizeNpcDeathTransition(HarvesterEngine &engine,
npcEntity->setHitTestMode(kEntityHitTestNone);
npcEntity->setVisible(true);
} else {
- sceneRuntime.removeSceneEntityByName(npc.npcName);
+ _sceneRuntime.removeSceneEntityByName(npc.npcName);
}
npc.active = false;
npc.visible = false;
@@ -1117,24 +1119,23 @@ Common::Error Combat::finalizeNpcDeathTransition(HarvesterEngine &engine,
}
}
- return interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
+ return _interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
}
-void Combat::startMonsterHitReaction(HarvesterEngine &engine,
- CombatEffects &combatEffects, MonsterRecord &monster, Entity &monsterEntity, MonsterCombatState *combatState,
+void Combat::startMonsterHitReaction(MonsterRecord &monster, Entity &monsterEntity, MonsterCombatState *combatState,
int attackerAttackFirstFrame, bool &needsRedraw) const {
- if (combatEffects.spawnCombatHitEffect(monsterEntity, monster.monsterName))
+ if (_combatEffects.spawnCombatHitEffect(monsterEntity, monster.monsterName))
needsRedraw = true;
if (!combatState) {
- (void)playRandomRoomAttackSound(engine,
+ (void)playRandomRoomAttackSound(_engine,
monster.hitSound1, monster.hitSound2, monster.hitSound3);
return;
}
HitAnimationRange range;
if (!resolveRoomMonsterHitAnimationRange(monsterEntity, attackerAttackFirstFrame, range)) {
- (void)playRandomRoomAttackSound(engine,
+ (void)playRandomRoomAttackSound(_engine,
monster.hitSound1, monster.hitSound2, monster.hitSound3);
debugC(1, kDebugCombat,
"Harvester: combat monster hit reaction skipped target='%s' attack_frame=%d reason='no native hit bank'",
@@ -1159,7 +1160,7 @@ void Combat::startMonsterHitReaction(HarvesterEngine &engine,
monsterEntity.setAnimationEnabled(true);
monsterEntity.setCurrentFrame(range.firstFrame);
if (!combatState->hitSoundPlayed && monster.hitSoundTriggerFrame <= 0) {
- (void)playRandomRoomAttackSound(engine,
+ (void)playRandomRoomAttackSound(_engine,
monster.hitSound1, monster.hitSound2, monster.hitSound3);
combatState->hitSoundPlayed = true;
}
@@ -1170,14 +1171,12 @@ void Combat::startMonsterHitReaction(HarvesterEngine &engine,
needsRedraw = true;
}
-Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupState &state,
- Player &player, EntityManager *entityManager, const Common::Point &mousePos,
- CombatEffects &combatEffects, Interaction &interactionProcessor, bool &needsRedraw) {
- const RoomPlayerState &playerState = player.getState();
- if (!engine.isCombatDebugEnabled())
+Common::Error Combat::killDebugActiveMonster(const Common::Point &mousePos, bool &needsRedraw) {
+ const RoomPlayerState &playerState = _player.getState();
+ if (!_engine.isCombatDebugEnabled())
return Common::kNoError;
- MonsterRecord *monster = resolveKillTarget(state, playerState, entityManager, mousePos);
- Entity *monsterEntity = monster ? findSceneRuntimeEntity(entityManager, monster->monsterName) : nullptr;
+ MonsterRecord *monster = resolveKillTarget(mousePos);
+ Entity *monsterEntity = monster ? findSceneRuntimeEntity(_entityManager, monster->monsterName) : nullptr;
if (!monster || !monsterEntity || !monsterEntity->isVisible()) {
debugC(1, kDebugCombat,
"Harvester: debug combat kill skipped reason='no active monster' cursor=(%d,%d)",
@@ -1185,7 +1184,7 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
return Common::kNoError;
}
- Script *script = engine.getScript();
+ Script *script = _engine.getScript();
if (!script) {
debugC(1, kDebugCombat,
"Harvester: debug combat kill skipped target='%s' reason='no startup script'",
@@ -1197,18 +1196,18 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
const int damageLanded = monster->currentHitPoints;
monster->currentHitPoints = 0;
if (damageLanded > 0)
- combatEffects.spawnCombatDamagePopup(*monsterEntity, monster->monsterName, damageLanded);
+ _combatEffects.spawnCombatDamagePopup(*monsterEntity, monster->monsterName, damageLanded);
if (playerState.attackTargetClassId == kEntityClassMonster &&
playerState.attackTargetName.equalsIgnoreCase(monster->monsterName)) {
- player.clearAttackTarget();
+ _player.clearAttackTarget();
}
debugC(1, kDebugCombat,
"Harvester: debug combat kill target='%s' damage=%d damage_type=%d cursor=(%d,%d)",
monster->monsterName.c_str(), damageLanded, debugDamageType, mousePos.x, mousePos.y);
- const int monsterIndex = findRoomMonsterIndexByName(state, monster->monsterName);
+ const int monsterIndex = findRoomMonsterIndexByName(_scene.state, monster->monsterName);
MonsterCombatState *combatState =
monsterIndex >= 0 && monsterIndex < (int)_monsterCombatStates.size()
? &_monsterCombatStates[(uint)monsterIndex]
@@ -1219,7 +1218,7 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
DeathAnimationRange deathRange;
if (combatState && resolveMonsterDeathAnimationRange(*monsterEntity, monster->facing,
- debugDamageType, engine.isGoreEnabled(), deathRange)) {
+ debugDamageType, _engine.isGoreEnabled(), deathRange)) {
combatState->deathActive = true;
combatState->deathFirstFrame = deathRange.firstFrame;
combatState->deathLastFrame = deathRange.lastFrame;
@@ -1230,7 +1229,7 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
monsterEntity->setAnimationEnabled(true);
monsterEntity->setCurrentFrame(deathRange.firstFrame);
if (!monster->deathSound.empty())
- (void)engine.playSound(monster->deathSound);
+ (void)_engine.playSound(monster->deathSound);
needsRedraw = true;
return Common::kNoError;
}
@@ -1250,36 +1249,32 @@ Common::Error Combat::killDebugActiveMonster(HarvesterEngine &engine, RoomSetupS
}
}
- return interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
+ return _interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
}
-Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetupState &state,
- Player &player, EntityManager *entityManager,
- SceneEntities &sceneRuntime, CombatEffects &combatEffects, const CheatSystem &cheats,
- InteractionCallbacks &callbacks, Interaction &interactionProcessor, bool &needsRedraw) {
- const RoomPlayerState &playerState = player.getState();
- if (!entityManager)
+Common::Error Combat::updateRoomMonsterCombat(bool &needsRedraw) {
+ const RoomPlayerState &playerState = _player.getState();
+ if (!_entityManager)
return Common::kNoError;
- Script &script = *engine.getScript();
+ Script &script = *_engine.getScript();
const uint32 now = Player::getRuntimeClockTicks();
const uint32 moveInterval = MAX<uint32>(1, 100U / (uint32)kRoomMonsterAnimationRate);
const int horizontalStepBase = 8;
const int depthStep = MAX<int>(1, roundRoomCombatFloat(
- state.roomZVelocityStep > 0.0f ? state.roomZVelocityStep : 1.0f));
+ _scene.state.roomZVelocityStep > 0.0f ? _scene.state.roomZVelocityStep : 1.0f));
bool playerAlive = script.getPlayerCurrentHitPoints() > 0;
- resizeCombatStates(state);
+ resizeCombatStates();
- const NpcCombatUpdateResult npcResult = updateRoomNpcCombat(engine, state,
- entityManager, sceneRuntime, interactionProcessor, needsRedraw);
+ const NpcCombatUpdateResult npcResult = updateRoomNpcCombat(needsRedraw);
if (npcResult.finalizedDeath)
return npcResult.error;
- for (uint i = 0; i < state.roomMonsters.size(); ++i) {
- MonsterRecord &monster = state.roomMonsters[i];
+ for (uint i = 0; i < _scene.state.roomMonsters.size(); ++i) {
+ MonsterRecord &monster = _scene.state.roomMonsters[i];
MonsterCombatState &combatState = _monsterCombatStates[i];
- Entity *entity = findSceneRuntimeEntity(entityManager, monster.monsterName);
+ Entity *entity = findSceneRuntimeEntity(_entityManager, monster.monsterName);
if (!entity || !monster.visible) {
clearRoomMonsterCombatState(combatState);
continue;
@@ -1302,7 +1297,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
monster.runtimeState,
monster.onDeathActionTag.c_str());
clearRoomMonsterCombatState(combatState);
- const bool herrillDeathQueued = queueInnerSanctumHerrillDeathAfterMuck(engine, state, monster);
+ const bool herrillDeathQueued = queueInnerSanctumHerrillDeathAfterMuck(monster);
InteractionResult interaction;
interaction.mutatedRuntimeState = true;
@@ -1321,7 +1316,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
interaction.visualRuntimeStateChanged = true;
}
- return interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
+ return _interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
}
continue;
}
@@ -1341,7 +1336,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
if (!combatState.hitSoundPlayed &&
monster.hitSoundTriggerFrame >= 0 &&
currentFrame >= combatState.hitFirstFrame + monster.hitSoundTriggerFrame) {
- (void)playRandomRoomAttackSound(engine,
+ (void)playRandomRoomAttackSound(_engine,
monster.hitSound1, monster.hitSound2, monster.hitSound3);
combatState.hitSoundPlayed = true;
}
@@ -1355,7 +1350,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
monster.posX + knockbackStep, monster.screenMinXBound, monster.screenMaxXBound);
if (monster.posX != previousX) {
(void)applyRoomActorPlacement(
- state, *entity, monster.posX, monster.posY, (float)monster.posZ);
+ _scene.state, *entity, monster.posX, monster.posY, (float)monster.posZ);
(void)script.syncRuntimeMonsterRecord(monster);
debugC(1, kDebugCombat,
"Harvester: combat monster hit knockback target='%s' from_x=%d to_x=%d remaining=%d",
@@ -1379,7 +1374,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
if (!combatState.attackSoundPlayed &&
monster.attackSoundTriggerFrame >= 0 &&
currentFrame >= combatState.attackFirstFrame + monster.attackSoundTriggerFrame) {
- (void)playRandomRoomAttackSound(engine,
+ (void)playRandomRoomAttackSound(_engine,
monster.attackSound1, monster.attackSound2, monster.attackSound3);
combatState.attackSoundPlayed = true;
}
@@ -1398,7 +1393,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
monster.monsterName.c_str(), currentFrame, script.getPlayerCurrentHitPoints());
} else {
const int playerHitPointsBefore = script.getPlayerCurrentHitPoints();
- const bool damageDisabled = cheats.isPlayerDamageDisabled();
+ const bool damageDisabled = _cheats.isPlayerDamageDisabled();
const bool changed = damageDisabled
? false
: script.adjustPlayerCurrentHitPoints(-monster.damageAmount);
@@ -1411,17 +1406,17 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
playerHitPointsBefore, playerHitPointsAfter, changed,
damageDisabled ? 1 : 0);
if (damageLanded > 0 && playerState.entity) {
- combatEffects.spawnCombatDamagePopup(*playerState.entity, playerState.entity->getName(), damageLanded);
- player.cancelIdleAnimation();
+ _combatEffects.spawnCombatDamagePopup(*playerState.entity, playerState.entity->getName(), damageLanded);
+ _player.cancelIdleAnimation();
if (playerHitPointsAfter > 0 &&
- player.startHitAnimation(engine, combatState.attackFirstFrame)) {
- callbacks.notePlayerActivity();
+ _player.startHitAnimation(_engine, combatState.attackFirstFrame)) {
+ _callbacks.notePlayerActivity();
}
}
if (changed && playerHitPointsAfter <= 0) {
playerAlive = false;
- callbacks.stopPlayerRegionInteraction();
- callbacks.startPlayerDefeatSequence(
+ _callbacks.stopPlayerRegionInteraction();
+ _callbacks.startPlayerDefeatSequence(
"combat_monster_hit", monster.monsterName, monster.damageType);
return Common::kNoError;
}
@@ -1462,15 +1457,15 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
const float absZDelta = zDelta >= 0.0f ? zDelta : -zDelta;
const int engageDistance = MAX(0, monster.engageDistance);
const int liveWaypointTolerance = roundRoomCombatFloat(
- Player::computeDepthScale(state,
+ Player::computeDepthScale(_scene.state,
MIN<float>(playerState.z, (float)monster.posZ)) * kNativeMonsterHorizontalWaypointTolerance);
bool attemptedMoveX = false;
bool attemptedMoveZ = false;
if (absZDelta > kNativeMonsterPursuitZTolerance) {
attemptedMoveZ = true;
monster.posZ = stepTowardsRoomCombatInt(monster.posZ, playerTargetZ, depthStep);
- monster.posZ = (int)clampRoomDepthForEvent(state, (float)monster.posZ);
- monster.posY = mapRoomDepthToScreenYForCombat(state, (float)monster.posZ, monster.posY);
+ monster.posZ = (int)clampRoomDepthForEvent(_scene.state, (float)monster.posZ);
+ monster.posY = mapRoomDepthToScreenYForCombat(_scene.state, (float)monster.posZ, monster.posY);
} else if (absLiveCenterDx > engageDistance) {
// Native class-6 pursuit stores a target frame-left X, not a center X.
const int desiredFrameLeftX = monsterCenterX < playerCenterX
@@ -1479,7 +1474,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
if (ABS(monsterRect.left - desiredFrameLeftX) > liveWaypointTolerance) {
attemptedMoveX = true;
const int step = MAX<int>(1, roundRoomCombatFloat(
- Player::computeDepthScale(state, (float)monster.posZ) * (float)horizontalStepBase));
+ Player::computeDepthScale(_scene.state, (float)monster.posZ) * (float)horizontalStepBase));
const int monsterFrameLeftOffset = monsterRect.left - monster.posX;
const int desiredLogicalCenterX = desiredFrameLeftX - monsterFrameLeftOffset;
monster.posX = stepTowardsRoomCombatInt(monster.posX, desiredLogicalCenterX, step);
@@ -1498,9 +1493,9 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
monster.facing = movedX < 0 ? 1 : 2;
else if (movedY != 0)
monster.facing = movedY < 0 ? 3 : 0;
- (void)applyRoomActorPlacement(state, *entity, monster.posX, monster.posY, (float)monster.posZ);
+ (void)applyRoomActorPlacement(_scene.state, *entity, monster.posX, monster.posY, (float)monster.posZ);
if (monster.posZ != previousZ)
- entityManager->reinsertSceneEntity(entity);
+ _entityManager->reinsertSceneEntity(entity);
(void)script.syncRuntimeMonsterRecord(monster);
debugC(3, kDebugCombat,
"Harvester: combat monster chase move monster='%s' live_center_dx=%d z_delta=%.2f engage=%d waypoint_tol=%d from=(%d,%d,z=%d) to=(%d,%d,z=%d) facing=%d",
@@ -1535,7 +1530,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
continue;
AttackAnimationRange range;
- if (!resolveMonsterAttackAnimationRange(engine, *entity, monsterCenterX, playerCenterX, range)) {
+ if (!resolveMonsterAttackAnimationRange(_engine, *entity, monsterCenterX, playerCenterX, range)) {
debugC(1, kDebugCombat,
"Harvester: combat monster attack skipped monster='%s' reason='no native attack bank' target_side=%s",
monster.monsterName.c_str(), playerCenterX < monsterCenterX ? "left" : "right");
@@ -1551,7 +1546,7 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
monster.attackSound1.empty() && monster.attackSound2.empty() && monster.attackSound3.empty();
combatState.attackContactResolved = false;
combatState.attackTargetName = playerState.entity->getName();
- combatState.attackCooldownSeedTick = now + engine.getRandomNumber(99);
+ combatState.attackCooldownSeedTick = now + _engine.getRandomNumber(99);
combatState.loggedPursuitStallDirections = 0;
monster.facing = range.resumeFacing;
entity->setAnimationFrameRange(range.firstFrame, range.lastFrame, false);
@@ -1573,19 +1568,15 @@ Common::Error Combat::updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetup
return Common::kNoError;
}
-Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
- RoomSetupState &state, Player &player,
- EntityManager *entityManager, SceneEntities &sceneRuntime,
- CombatEffects &combatEffects,
- Interaction &interactionProcessor, bool &needsRedraw) {
- const RoomPlayerState &playerState = player.getState();
+Common::Error Combat::resolvePlayerAttackContact(bool &needsRedraw) {
+ const RoomPlayerState &playerState = _player.getState();
if (!playerState.attackActive || playerState.attackContactResolved || !playerState.entity ||
playerState.attackContactFrame < 0 ||
playerState.entity->getCurrentFrame() < playerState.attackContactFrame) {
return Common::kNoError;
}
- player.markAttackContactResolved();
+ _player.markAttackContactResolved();
const int damageType = Player::resolveCombatLoadoutDamageType(playerState.combatLoadout);
const int damageAmount = Player::resolveCombatLoadoutDamageAmount(playerState.combatLoadout);
debugC(1, kDebugCombat,
@@ -1594,14 +1585,14 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
Player::describeCombatLoadout(playerState.combatLoadout), damageAmount,
Player::describeCombatDamageType(damageType),
describeCombatTargetClass(playerState.attackTargetClassId), playerState.attackTargetName.c_str());
- Script *script = engine.getScript();
+ Script *script = _engine.getScript();
if (!script)
return Common::kNoError;
- captureOverlappingNpcAttackTarget(state, player, entityManager);
+ captureOverlappingNpcAttackTarget();
if (playerState.attackTargetClassId == kEntityClassNpc) {
Entity *npcEntity = nullptr;
- NpcRecord *npc = selectNpcAttackContactTarget(state, playerState, entityManager, npcEntity);
+ NpcRecord *npc = selectNpcAttackContactTarget(npcEntity);
if (!npc) {
debugC(1, kDebugCombat,
"Harvester: combat player attack missed class='npc' target='%s' reason='no reachable npc'",
@@ -1614,7 +1605,7 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
const bool jimmyFlagChanged = npc->npcName.equalsIgnoreCase("JIMMY")
? script->setRuntimeFlagValue("JIMMY_ATTACKED", true)
: false;
- const int npcIndex = findRoomNpcIndexByName(state, npc->npcName);
+ const int npcIndex = findRoomNpcIndexByName(_scene.state, npc->npcName);
NpcCombatState *combatState =
npcIndex >= 0 && npcIndex < (int)_npcCombatStates.size()
? &_npcCombatStates[(uint)npcIndex]
@@ -1631,11 +1622,11 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
return Common::kNoError;
if (runtimeChanged && npcEntity) {
const Common::String followTargetName = npc->monsterfyTargetName;
- if (combatEffects.spawnCombatHitEffect(*npcEntity, followTargetName))
+ if (_combatEffects.spawnCombatHitEffect(*npcEntity, followTargetName))
needsRedraw = true;
}
if (runtimeChanged && combatState && npcEntity &&
- beginNpcDeathTransition(engine, *npc, *npcEntity, *combatState, damageType, needsRedraw))
+ beginNpcDeathTransition(*npc, *npcEntity, *combatState, damageType, needsRedraw))
return Common::kNoError;
if (runtimeChanged) {
debugC(1, kDebugCombat,
@@ -1643,14 +1634,14 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
npc->npcName.c_str(), damageType, npc->onDeathActionTag.c_str());
NpcCombatState fallbackState;
fallbackState.deathDamageType = damageType;
- return finalizeNpcDeathTransition(engine, entityManager, sceneRuntime, *npc, combatState ? *combatState : fallbackState, interactionProcessor, needsRedraw);
+ return finalizeNpcDeathTransition(*npc, combatState ? *combatState : fallbackState, needsRedraw);
}
return Common::kNoError;
}
Entity *monsterEntity = nullptr;
- MonsterRecord *monster = selectMonsterAttackContactTarget(state, player, entityManager, monsterEntity);
+ MonsterRecord *monster = selectMonsterAttackContactTarget(monsterEntity);
if (!monster || !monsterEntity) {
debugC(1, kDebugCombat,
"Harvester: combat player attack missed class='monster' target='%s' reason='no reachable monster'",
@@ -1662,7 +1653,7 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
monster->currentHitPoints = MAX(0,
monster->currentHitPoints - damageAmount);
const int damageLanded = hitPointsBefore - monster->currentHitPoints;
- const int monsterIndex = findRoomMonsterIndexByName(state, monster->monsterName);
+ const int monsterIndex = findRoomMonsterIndexByName(_scene.state, monster->monsterName);
MonsterCombatState *combatState =
monsterIndex >= 0 && monsterIndex < (int)_monsterCombatStates.size()
? &_monsterCombatStates[(uint)monsterIndex]
@@ -1673,8 +1664,8 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
Player::describeCombatLoadout(playerState.combatLoadout), damageAmount,
Player::describeCombatDamageType(damageType), hitPointsBefore, monster->currentHitPoints);
if (damageLanded > 0) {
- combatEffects.spawnCombatDamagePopup(*monsterEntity, monster->monsterName, damageLanded);
- startMonsterHitReaction(engine, combatEffects, *monster, *monsterEntity, combatState, playerState.attackFirstFrame, needsRedraw);
+ _combatEffects.spawnCombatDamagePopup(*monsterEntity, monster->monsterName, damageLanded);
+ startMonsterHitReaction(*monster, *monsterEntity, combatState, playerState.attackFirstFrame, needsRedraw);
}
if (monster->currentHitPoints > 0) {
(void)script->syncRuntimeMonsterRecord(*monster);
@@ -1687,7 +1678,7 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
DeathAnimationRange deathRange;
if (combatState && resolveMonsterDeathAnimationRange(*monsterEntity, monster->facing,
- damageType, engine.isGoreEnabled(), deathRange)) {
+ damageType, _engine.isGoreEnabled(), deathRange)) {
combatState->deathActive = true;
combatState->deathFirstFrame = deathRange.firstFrame;
combatState->deathLastFrame = deathRange.lastFrame;
@@ -1698,19 +1689,19 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
monsterEntity->setAnimationEnabled(true);
monsterEntity->setCurrentFrame(deathRange.firstFrame);
if (!monster->deathSound.empty())
- (void)engine.playSound(monster->deathSound);
+ (void)_engine.playSound(monster->deathSound);
debugC(1, kDebugCombat,
"Harvester: combat monster death start target='%s' damage_type=%d frames=%d..%d gore=%d on_death='%s'",
monster->monsterName.c_str(), damageType,
deathRange.firstFrame, deathRange.lastFrame,
- engine.isGoreEnabled(), monster->onDeathActionTag.c_str());
+ _engine.isGoreEnabled(), monster->onDeathActionTag.c_str());
needsRedraw = true;
return Common::kNoError;
}
monster->active = false;
monster->visible = false;
- const bool herrillDeathQueued = queueInnerSanctumHerrillDeathAfterMuck(engine, state, *monster);
+ const bool herrillDeathQueued = queueInnerSanctumHerrillDeathAfterMuck(*monster);
debugC(1, kDebugCombat,
"Harvester: combat monster defeated target='%s' on_death='%s' fallback='no death bank'",
monster->monsterName.c_str(), monster->onDeathActionTag.c_str());
@@ -1731,21 +1722,21 @@ Common::Error Combat::resolvePlayerAttackContact(HarvesterEngine &engine,
interaction.visualRuntimeStateChanged = true;
}
- return interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
+ return _interactionProcessor.handleCombatInteraction(interaction, needsRedraw);
}
-void Combat::initializeCombatStates(const RoomSetupState &state) {
- _monsterCombatStates.resize(state.roomMonsters.size());
- _npcCombatStates.resize(state.roomNpcs.size());
+void Combat::initializeCombatStates() {
+ _monsterCombatStates.resize(_scene.state.roomMonsters.size());
+ _npcCombatStates.resize(_scene.state.roomNpcs.size());
debugC(1, kDebugCombat, "Harvester: initialized room combat states monsters=%u npcs=%u",
_monsterCombatStates.size(), _npcCombatStates.size());
}
-void Combat::resizeCombatStates(const RoomSetupState &state) {
- if (_npcCombatStates.size() != state.roomNpcs.size())
- _npcCombatStates.resize(state.roomNpcs.size());
- if (_monsterCombatStates.size() != state.roomMonsters.size())
- _monsterCombatStates.resize(state.roomMonsters.size());
+void Combat::resizeCombatStates() {
+ if (_npcCombatStates.size() != _scene.state.roomNpcs.size())
+ _npcCombatStates.resize(_scene.state.roomNpcs.size());
+ if (_monsterCombatStates.size() != _scene.state.roomMonsters.size())
+ _monsterCombatStates.resize(_scene.state.roomMonsters.size());
}
Common::Array<MonsterCombatState> Combat::prepareMonsterCombatStatesForSceneChange(
@@ -1773,10 +1764,10 @@ void Combat::commitMonsterCombatStatesForSceneChange(Common::Array<MonsterCombat
debugC(2, kDebugCombat, "Harvester: committed room monster combat states count=%u", _monsterCombatStates.size());
}
-void Combat::resetForSceneRefresh(const RoomSetupState &state) {
+void Combat::resetForSceneRefresh() {
// NPC death state survives refresh and is resized by index at the next combat update.
_monsterCombatStates.clear();
- _monsterCombatStates.resize(state.roomMonsters.size());
+ _monsterCombatStates.resize(_scene.state.roomMonsters.size());
debugC(2, kDebugCombat, "Harvester: reset room monster combat states count=%u retained_npcs=%u",
_monsterCombatStates.size(), _npcCombatStates.size());
}
diff --git a/engines/harvester/combat.h b/engines/harvester/combat.h
index 4d8e9d2d8df..40b64d192a1 100644
--- a/engines/harvester/combat.h
+++ b/engines/harvester/combat.h
@@ -36,7 +36,6 @@ class InteractionCallbacks;
class Interaction;
class SceneEntities;
class Player;
-struct RoomPlayerState;
extern const int kRoomMonsterAnimationRate;
extern const int kNativeMonsterAttackAnimationRate;
@@ -132,65 +131,61 @@ struct NpcCombatUpdateResult {
class Combat {
public:
- void initializeCombatStates(const RoomSetupState &state);
+ Combat(HarvesterEngine &engine, SceneState &scene, Player &player,
+ EntityManager *entityManager, SceneEntities &sceneRuntime, CombatEffects &combatEffects,
+ const CheatSystem &cheats, InteractionCallbacks &callbacks, Interaction &interactionProcessor);
+ Combat(const Combat &) = delete;
+ Combat &operator=(const Combat &) = delete;
+
+ void initializeCombatStates();
// Keep prepared state separate until scene-entity mutations succeed.
Common::Array<MonsterCombatState> prepareMonsterCombatStatesForSceneChange(
const Common::Array<MonsterRecord> &previousMonsters, const Common::Array<MonsterRecord> &updatedMonsters) const;
void commitMonsterCombatStatesForSceneChange(Common::Array<MonsterCombatState> &&states);
- void resetForSceneRefresh(const RoomSetupState &state);
+ void resetForSceneRefresh();
- void capturePlayerAttackTargetForKeyboard(RoomSetupState &state, Player &player,
- EntityManager *entityManager, bool attackLeft, bool attackRight, bool attackUp, bool attackDown) const;
- MonsterRecord *resolveKillTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager, const Common::Point &mousePos) const;
+ void capturePlayerAttackTargetForKeyboard(bool attackLeft, bool attackRight, bool attackUp, bool attackDown) const;
+ MonsterRecord *resolveKillTarget(const Common::Point &mousePos) const;
// The caller clears the captured target before resolving the room hover state.
- void capturePlayerAttackTarget(RoomSetupState &state, Player &player,
- EntityManager *entityManager, const Common::Point &mousePos, const NpcRecord *hoverNpc) const;
- void captureOverlappingNpcAttackTarget(RoomSetupState &state, Player &player, EntityManager *entityManager) const;
- NpcRecord *selectNpcAttackContactTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager, Entity *&npcEntity) const;
- MonsterRecord *selectMonsterAttackContactTarget(RoomSetupState &state, Player &player,
- EntityManager *entityManager, Entity *&monsterEntity) const;
-
- Common::Error killDebugActiveMonster(HarvesterEngine &engine, RoomSetupState &state,
- Player &player, EntityManager *entityManager, const Common::Point &mousePos,
- CombatEffects &combatEffects, Interaction &interactionProcessor, bool &needsRedraw);
-
- Common::Error updateRoomMonsterCombat(HarvesterEngine &engine, RoomSetupState &state,
- Player &player, EntityManager *entityManager,
- SceneEntities &sceneRuntime, CombatEffects &combatEffects, const CheatSystem &cheats,
- InteractionCallbacks &callbacks, Interaction &interactionProcessor, bool &needsRedraw);
- Common::Error resolvePlayerAttackContact(HarvesterEngine &engine,
- RoomSetupState &state, Player &player,
- EntityManager *entityManager, SceneEntities &sceneRuntime,
- CombatEffects &combatEffects,
- Interaction &interactionProcessor, bool &needsRedraw);
+ void capturePlayerAttackTarget(const Common::Point &mousePos, const NpcRecord *hoverNpc) const;
+ void captureOverlappingNpcAttackTarget() const;
+ NpcRecord *selectNpcAttackContactTarget(Entity *&npcEntity) const;
+ MonsterRecord *selectMonsterAttackContactTarget(Entity *&monsterEntity) const;
+
+ Common::Error killDebugActiveMonster(const Common::Point &mousePos, bool &needsRedraw);
+
+ Common::Error updateRoomMonsterCombat(bool &needsRedraw);
+ Common::Error resolvePlayerAttackContact(bool &needsRedraw);
private:
- void resizeCombatStates(const RoomSetupState &state);
- bool queueInnerSanctumHerrillDeathAfterMuck(HarvesterEngine &engine, RoomSetupState &state, const MonsterRecord &monster) const;
+ void resizeCombatStates();
+ bool queueInnerSanctumHerrillDeathAfterMuck(const MonsterRecord &monster) const;
// Called after resizeCombatStates; NPC finalization ends the entire combat update.
- NpcCombatUpdateResult updateRoomNpcCombat(HarvesterEngine &engine, RoomSetupState &state,
- EntityManager *entityManager, SceneEntities &sceneRuntime,
- Interaction &interactionProcessor, bool &needsRedraw);
-
- bool beginNpcDeathTransition(HarvesterEngine &engine,
- NpcRecord &npc, Entity &npcEntity, NpcCombatState &combatState, int deathDamageType, bool &needsRedraw) const;
- Common::Error finalizeNpcDeathTransition(HarvesterEngine &engine,
- EntityManager *entityManager, SceneEntities &sceneRuntime, NpcRecord &npc, NpcCombatState &combatState,
- Interaction &interactionProcessor, bool &needsRedraw) const;
-
- void startMonsterHitReaction(HarvesterEngine &engine,
- CombatEffects &combatEffects, MonsterRecord &monster, Entity &monsterEntity, MonsterCombatState *combatState,
- int attackerAttackFirstFrame, bool &needsRedraw) const;
+ NpcCombatUpdateResult updateRoomNpcCombat(bool &needsRedraw);
+
+ bool beginNpcDeathTransition(NpcRecord &npc, Entity &npcEntity, NpcCombatState &combatState,
+ int deathDamageType, bool &needsRedraw) const;
+ Common::Error finalizeNpcDeathTransition(NpcRecord &npc, NpcCombatState &combatState, bool &needsRedraw) const;
- MonsterRecord *findMonsterTargetAtPoint(RoomSetupState &state, EntityManager *entityManager, const Common::Point &point) const;
- MonsterRecord *findOverlappingMonsterTarget(RoomSetupState &state, const RoomPlayerState &playerState, EntityManager *entityManager) const;
- NpcRecord *findOverlappingNpcTarget(RoomSetupState &state, const RoomPlayerState &playerState, EntityManager *entityManager) const;
- bool playerAttackCanReachTarget(RoomSetupState &state, const RoomPlayerState &playerState, Entity *targetEntity, int engageDistance = 0) const;
- MonsterRecord *findProjectileContactMonsterTarget(RoomSetupState &state, const RoomPlayerState &playerState,
- EntityManager *entityManager) const;
+ void startMonsterHitReaction(MonsterRecord &monster, Entity &monsterEntity, MonsterCombatState *combatState,
+ int attackerAttackFirstFrame, bool &needsRedraw) const;
+ MonsterRecord *findMonsterTargetAtPoint(const Common::Point &point) const;
+ MonsterRecord *findOverlappingMonsterTarget() const;
+ NpcRecord *findOverlappingNpcTarget() const;
+ bool playerAttackCanReachTarget(Entity *targetEntity, int engageDistance = 0) const;
+ MonsterRecord *findProjectileContactMonsterTarget() const;
+
+ HarvesterEngine &_engine;
+ // Refresh assigns new room data into this scene object.
+ SceneState &_scene;
+ Player &_player;
+ EntityManager *const _entityManager;
+ SceneEntities &_sceneRuntime;
+ CombatEffects &_combatEffects;
+ const CheatSystem &_cheats;
+ InteractionCallbacks &_callbacks;
+ Interaction &_interactionProcessor;
Common::Array<MonsterCombatState> _monsterCombatStates;
Common::Array<NpcCombatState> _npcCombatStates;
};
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index 9e938eab48a..c917dc985b0 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -130,7 +130,9 @@ Scene::Scene(HarvesterEngine &engine, Flow &flow, SceneState &scene, EntityManag
_presentation(engine, scene, view.art, view.inspectFont, view.useNativeInspectFont),
_interactionProcessor(engine, flow, scene, _player, _pendingRegionName, _pendingTransition.roomName,
_pendingTransition.isRoomName, _pendingTransition.usesSavedRoomState, _pendingTransition.savedRoomState,
- canExitCloseupToParent, *this) {
+ canExitCloseupToParent, *this),
+ _combat(engine, scene, _player, entityManager, _sceneRuntime, _combatEffects,
+ cheats, *this, _interactionProcessor) {
}
void Scene::resetIdleState() {
@@ -247,7 +249,7 @@ bool Scene::refreshCurrentScene(bool preservePlayerPlacement) {
_sceneRuntime.restoreRoomMonsterAnimations();
_roomItems.hideCarriedRoomItem();
_player.rebindAfterSceneRefresh(_engine, _scene.state, _entityManager, preservePlayerPlacement);
- _combat.resetForSceneRefresh(_scene.state);
+ _combat.resetForSceneRefresh();
_pendingRegionName.clear();
resetIdleState();
_flow.resetCursorAnimationSequence();
@@ -259,7 +261,7 @@ void Scene::initializePlayerState() {
_player.initialize(_scene.state,
_entityManager ? _entityManager->findSceneEntityByName("PLAYER") : nullptr,
_engine.getScript() ? _engine.getScript()->getPlayerCombatLoadout() : 0);
- _combat.initializeCombatStates(_scene.state);
+ _combat.initializeCombatStates();
}
void Scene::syncAnimatedRoomActorPlacement() {
@@ -582,7 +584,7 @@ void Scene::updatePlayerControls(const PlayerControlState &control, bool &needsR
!idleState.active && !idleState.exiting) {
const uint32 now = Player::getRuntimeClockTicks();
if (_inputState.nextKeyboardAttackAllowedTick == 0 || (int32)(now - _inputState.nextKeyboardAttackAllowedTick) >= 0) {
- _combat.capturePlayerAttackTargetForKeyboard(_scene.state, _player, _entityManager,
+ _combat.capturePlayerAttackTargetForKeyboard(
_inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown);
if (_player.startKeyboardAttackAnimation(_scene.state,
_inputState.moveLeft, _inputState.moveRight, _inputState.moveUp, _inputState.moveDown)) {
@@ -864,13 +866,11 @@ Common::Error Scene::tryActivatePassiveRegion(bool &needsRedraw) {
}
Common::Error Scene::resolvePlayerAttackContact(bool &needsRedraw) {
- return _combat.resolvePlayerAttackContact(_engine, _scene.state, _player, _entityManager,
- _sceneRuntime, _combatEffects, _interactionProcessor, needsRedraw);
+ return _combat.resolvePlayerAttackContact(needsRedraw);
}
Common::Error Scene::updateRoomMonsterCombat(bool &needsRedraw) {
- return _combat.updateRoomMonsterCombat(_engine, _scene.state, _player, _entityManager,
- _sceneRuntime, _combatEffects, _cheats, *this, _interactionProcessor, needsRedraw);
+ return _combat.updateRoomMonsterCombat(needsRedraw);
}
void Scene::syncCombatHitEffects(bool &needsRedraw) {
@@ -884,12 +884,11 @@ void Scene::updateIdleAnimation(bool &needsRedraw) {
}
void Scene::capturePlayerAttackTarget(const Common::Point &mousePos, const NpcRecord *npc) {
- _combat.capturePlayerAttackTarget(_scene.state, _player, _entityManager, mousePos, npc);
+ _combat.capturePlayerAttackTarget(mousePos, npc);
}
Common::Error Scene::killDebugActiveMonster(const Common::Point &mousePos, bool &needsRedraw) {
- return _combat.killDebugActiveMonster(_engine, _scene.state, _player, _entityManager,
- mousePos, _combatEffects, _interactionProcessor, needsRedraw);
+ return _combat.killDebugActiveMonster(mousePos, needsRedraw);
}
static const CftFontResource *findStartupFontByName(const HarvesterEngine &engine, const char *fontName) {
diff --git a/engines/harvester/scene.h b/engines/harvester/scene.h
index 733a276743e..f8a157b8d2f 100644
--- a/engines/harvester/scene.h
+++ b/engines/harvester/scene.h
@@ -126,7 +126,6 @@ private:
InventorySystem &_inventory;
SceneEntities _sceneRuntime;
Player _player;
- Combat _combat;
CombatEffects _combatEffects;
InputState _inputState;
Common::String _pendingRegionName;
@@ -138,6 +137,7 @@ private:
ItemInteractions _roomItems;
RoomPresentation _presentation;
Interaction _interactionProcessor;
+ Combat _combat;
};
} // End of namespace Harvester
Commit: a99abfd26a1bc8b7a62a642a99cff4782cea7218
https://github.com/scummvm/scummvm/commit/a99abfd26a1bc8b7a62a642a99cff4782cea7218
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: add an explicit execution context for scripts
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/cheats.cpp
engines/harvester/cheats.h
engines/harvester/combat.cpp
engines/harvester/dialogue.cpp
engines/harvester/dialogue.h
engines/harvester/flow.cpp
engines/harvester/flow.h
engines/harvester/input.cpp
engines/harvester/interaction.cpp
engines/harvester/npc/dialogue_runtime.h
engines/harvester/room_support.h
engines/harvester/scene.cpp
engines/harvester/script.cpp
engines/harvester/script.h
diff --git a/engines/harvester/cheats.cpp b/engines/harvester/cheats.cpp
index e58bebe9158..0652269e829 100644
--- a/engines/harvester/cheats.cpp
+++ b/engines/harvester/cheats.cpp
@@ -180,7 +180,7 @@ CheatInputResult CheatSystem::matchKey(uint16 ascii, CheatId &cheatId) {
}
CheatInputResult CheatSystem::processKey(const Common::KeyState &key, Script &script,
- const Common::String &roomName, InteractionResult &interaction,
+ const ScriptExecutionContext &executionContext, InteractionResult &interaction,
CheatActivation &activation) {
interaction = InteractionResult();
activation = CheatActivation();
@@ -188,12 +188,12 @@ CheatInputResult CheatSystem::processKey(const Common::KeyState &key, Script &sc
CheatId cheatId = kCheatMaxHealth;
const CheatInputResult inputResult = matchKey(key.ascii, cheatId);
if (inputResult == kCheatInputComplete)
- execute(cheatId, script, roomName, interaction, activation);
+ execute(cheatId, script, executionContext, interaction, activation);
return inputResult;
}
-void CheatSystem::execute(CheatId cheatId, Script &script, const Common::String &roomName,
+void CheatSystem::execute(CheatId cheatId, Script &script, const ScriptExecutionContext &executionContext,
InteractionResult &interaction, CheatActivation &activation) {
const bool hasHarvestBlade = script.isObjectInInventory(kHarvestBladeObjectName);
const bool requiresHarvestBlade = cheatId == kCheatLodgeLevel2 ||
@@ -243,17 +243,17 @@ void CheatSystem::execute(CheatId cheatId, Script &script, const Common::String
break;
case kCheatLodgeLevel2:
activation.hasInteraction = script.executeActionTag(
- "FOUNTAIN_ART1", interaction, true, roomName);
+ "FOUNTAIN_ART1", interaction, true, executionContext);
break;
case kCheatLodgeLevel3:
activation.clearInteractionState = true;
activation.hasInteraction = script.executeActionTag(
- "3RD_2_3RDNTRYR", interaction, true, roomName);
+ "3RD_2_3RDNTRYR", interaction, true, executionContext);
break;
case kCheatLodgeFinalLevel:
activation.clearInteractionState = true;
activation.hasInteraction = script.executeActionTag(
- "L2_M1", interaction, true, roomName);
+ "L2_M1", interaction, true, executionContext);
break;
case kCheatInvincibility:
activation.clearInteractionState = true;
@@ -263,7 +263,7 @@ void CheatSystem::execute(CheatId cheatId, Script &script, const Common::String
case kCheatLodgeLevel1:
activation.clearInteractionState = true;
activation.hasInteraction = script.executeActionTag(
- "WARP_TO_LODGE", interaction, true, roomName);
+ "WARP_TO_LODGE", interaction, true, executionContext);
break;
}
@@ -272,7 +272,7 @@ void CheatSystem::execute(CheatId cheatId, Script &script, const Common::String
!activation.hasInteraction) {
debugC(1, kDebugGeneral,
"Harvester: cheat action tag produced no interaction id='%s' room='%s'",
- describe(cheatId), roomName.c_str());
+ describe(cheatId), executionContext.roomName().c_str());
}
debugC(2, kDebugGeneral,
diff --git a/engines/harvester/cheats.h b/engines/harvester/cheats.h
index fd6ab757a74..a22cd3027d8 100644
--- a/engines/harvester/cheats.h
+++ b/engines/harvester/cheats.h
@@ -32,6 +32,7 @@ namespace Harvester {
class HarvesterEngine;
class Script;
+class ScriptExecutionContext;
struct InteractionResult;
enum CheatInputResult {
@@ -53,7 +54,7 @@ public:
explicit CheatSystem(HarvesterEngine &engine);
CheatInputResult processKey(const Common::KeyState &key, Script &script,
- const Common::String &roomName, InteractionResult &interaction,
+ const ScriptExecutionContext &executionContext, InteractionResult &interaction,
CheatActivation &activation);
void reset();
bool isPlayerDamageDisabled() const { return _playerDamageDisabled; }
@@ -72,7 +73,7 @@ private:
CheatInputResult matchKey(uint16 ascii, CheatId &cheatId);
static const char *describe(CheatId cheatId);
- void execute(CheatId cheatId, Script &script, const Common::String &roomName,
+ void execute(CheatId cheatId, Script &script, const ScriptExecutionContext &executionContext,
InteractionResult &interaction, CheatActivation &activation);
HarvesterEngine &_engine;
diff --git a/engines/harvester/combat.cpp b/engines/harvester/combat.cpp
index 8c59eb59662..64451dbcc14 100644
--- a/engines/harvester/combat.cpp
+++ b/engines/harvester/combat.cpp
@@ -1112,7 +1112,8 @@ Common::Error Combat::finalizeNpcDeathTransition(NpcRecord &npc, NpcCombatState
interaction.visualRuntimeStateChanged = runtimeChanged;
if (script && !npc.onDeathActionTag.empty()) {
InteractionResult deathInteraction;
- if (script->executeActionTag(npc.onDeathActionTag, deathInteraction, true, npc.roomName)) {
+ if (script->executeActionTag(npc.onDeathActionTag, deathInteraction, true,
+ ScriptExecutionContext::forNpcDeath(npc))) {
interaction = Common::move(deathInteraction);
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
@@ -1242,7 +1243,7 @@ Common::Error Combat::killDebugActiveMonster(const Common::Point &mousePos, bool
if (!monster->onDeathActionTag.empty()) {
InteractionResult deathInteraction;
if (script->executeActionTag(
- monster->onDeathActionTag, deathInteraction, true, monster->roomName)) {
+ monster->onDeathActionTag, deathInteraction, true, ScriptExecutionContext::forMonsterDeath(*monster))) {
interaction = Common::move(deathInteraction);
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
@@ -1305,7 +1306,7 @@ Common::Error Combat::updateRoomMonsterCombat(bool &needsRedraw) {
if (!monster.onDeathActionTag.empty()) {
InteractionResult deathInteraction;
if (script.executeActionTag(
- monster.onDeathActionTag, deathInteraction, true, monster.roomName)) {
+ monster.onDeathActionTag, deathInteraction, true, ScriptExecutionContext::forMonsterDeath(monster))) {
interaction = Common::move(deathInteraction);
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
@@ -1711,7 +1712,7 @@ Common::Error Combat::resolvePlayerAttackContact(bool &needsRedraw) {
if (!monster->onDeathActionTag.empty()) {
InteractionResult deathInteraction;
if (script->executeActionTag(
- monster->onDeathActionTag, deathInteraction, true, monster->roomName)) {
+ monster->onDeathActionTag, deathInteraction, true, ScriptExecutionContext::forMonsterDeath(*monster))) {
interaction = Common::move(deathInteraction);
interaction.mutatedRuntimeState = true;
interaction.visualRuntimeStateChanged = true;
diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index 2626ea93933..17fb1e6b568 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -1425,7 +1425,7 @@ void DialogueSystem::syncRuntimeSaveState(Common::Serializer &s) {
}
Common::Error DialogueSystem::runRoomNpcDialogue(const IndexedBitmap &backdrop, const byte *palette,
- float paletteBrightness, const Common::String ¤tRoomName,
+ float paletteBrightness, const ScriptExecutionContext &executionContext,
const NpcRecord &npc, const Common::String &usedItemName,
Flow &flow) {
Script *script = _engine.getScript();
@@ -1457,7 +1457,7 @@ Common::Error DialogueSystem::runRoomNpcDialogue(const IndexedBitmap &backdrop,
return Common::kReadingFailed;
// START_DIALOG may invoke an NPC assigned to another room.
DialogueRuntime runtime(
- _engine, *script, *text, flow, currentRoomName, session.getGenericByeTopic(), session);
+ _engine, *script, *text, flow, executionContext, session.getGenericByeTopic(), session);
return handler->handleDialogue(runtime, usedItemName, _sharedDialogueState);
}
diff --git a/engines/harvester/dialogue.h b/engines/harvester/dialogue.h
index d006caedf21..5ef2c8b8664 100644
--- a/engines/harvester/dialogue.h
+++ b/engines/harvester/dialogue.h
@@ -50,7 +50,7 @@ public:
void resetRoomNpcDialogueState();
void syncRuntimeSaveState(Common::Serializer &s);
Common::Error runRoomNpcDialogue(const IndexedBitmap &backdrop, const byte *palette,
- float paletteBrightness, const Common::String ¤tRoomName,
+ float paletteBrightness, const ScriptExecutionContext &executionContext,
const NpcRecord &npc, const Common::String &usedItemName,
Flow &flow);
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 83844608f46..6bb61ba9653 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -1751,12 +1751,12 @@ Common::Error Flow::runRoomMenu(const IndexedBitmap &backdrop, const byte *palet
}
Common::Error Flow::runRoomNpcDialogue(const IndexedBitmap &backdrop, const byte *palette,
- float paletteBrightness, const Common::String ¤tRoomName,
+ float paletteBrightness, const ScriptExecutionContext &executionContext,
const NpcRecord &npc, const Common::String &usedItemName) {
_queuedDialogueInteraction = InteractionResult();
_hasQueuedDialogueInteraction = false;
return _dialogue.runRoomNpcDialogue(backdrop, palette, paletteBrightness,
- currentRoomName, npc, usedItemName, *this);
+ executionContext, npc, usedItemName, *this);
}
Common::Error Flow::runTownMapSelector(const Common::String &mapEntryName,
diff --git a/engines/harvester/flow.h b/engines/harvester/flow.h
index 212399c4849..804c01862ea 100644
--- a/engines/harvester/flow.h
+++ b/engines/harvester/flow.h
@@ -75,7 +75,7 @@ private:
Common::Error runRoomMenu(const IndexedBitmap &backdrop, const byte *palette,
float paletteBrightness, bool canSaveGame);
Common::Error runRoomNpcDialogue(const IndexedBitmap &backdrop, const byte *palette,
- float paletteBrightness, const Common::String ¤tRoomName,
+ float paletteBrightness, const ScriptExecutionContext &executionContext,
const NpcRecord &npc, const Common::String &usedItemName);
Common::Error runTownMapSelector(const Common::String &mapEntryName, Common::String &destinationEntranceName);
Common::Error runRoomLoop(const Common::String &entranceName);
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index d4db61fbeb5..abe6160033b 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -220,7 +220,7 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
InteractionResult interaction;
bool didTransition = false;
const bool executedActionTag = _engine.getScript()->executeActionTag(
- secondaryAction.actionTag, interaction, true, _scene.state.roomName);
+ secondaryAction.actionTag, interaction, true, _scene.executionContext());
debugC(1, kDebugInventory,
"Harvester: inventory right click executeActionTag('%s') -> %d music='%s' cutscene='%s' nextRoom='%s'",
secondaryAction.actionTag.c_str(), executedActionTag,
@@ -574,7 +574,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
InteractionResult interaction;
if (!_engine.getScript()->resolveObjectInteraction(
- *clickedObject, interaction, _scene.state.roomName)) {
+ *clickedObject, interaction, _scene.executionContext())) {
if (canShowInspectText) {
beginInspectText(*clickedObject, resolvedInspectText);
} else if (hasInspectText) {
@@ -625,7 +625,7 @@ InputResult Input::handleKeyDown(const Common::KeyState &key, bool &needsRedraw)
InteractionResult cheatInteraction;
CheatActivation cheatActivation;
const CheatInputResult cheatInputResult = _cheats.processKey(
- key, *script, _scene.state.roomName,
+ key, *script, _scene.executionContext(),
cheatInteraction, cheatActivation);
if (cheatInputResult != kCheatInputIgnored) {
if (cheatInputResult == kCheatInputComplete && cheatActivation.activated) {
diff --git a/engines/harvester/interaction.cpp b/engines/harvester/interaction.cpp
index 2cc52ad8511..09bd3be59c9 100644
--- a/engines/harvester/interaction.cpp
+++ b/engines/harvester/interaction.cpp
@@ -178,7 +178,7 @@ Common::Error ItemInteractions::moveRoomItemDirectlyToInventory(const ObjectReco
if (shouldDispatchPickupActionOnDirectInventoryTransfer(object)) {
InteractionResult pickupInteraction;
if (script->executeActionTag(
- object.actionTag, pickupInteraction, true, _scene.state.roomName)) {
+ object.actionTag, pickupInteraction, true, _scene.executionContext())) {
Common::Error interactionError =
interactionProcessor.handleInteractionResult(
pickupInteraction, didTransition, Common::String());
@@ -229,7 +229,7 @@ Common::Error ItemInteractions::beginRoomItemCarry(const ObjectRecord &object,
if (shouldDispatchPickupActionOnCarryStart(object)) {
InteractionResult pickupInteraction;
if (script->executeActionTag(
- object.actionTag, pickupInteraction, true, _scene.state.roomName)) {
+ object.actionTag, pickupInteraction, true, _scene.executionContext())) {
Common::Error interactionError =
interactionProcessor.handleInteractionResult(
pickupInteraction, didTransition, Common::String());
@@ -275,7 +275,7 @@ Common::Error ItemInteractions::handleSelectedItemTargetInteraction(const Object
const Common::String selectedItemName = getSelectedItemName();
InteractionResult interaction;
const bool handled = _engine.getScript()->resolveUseItemInteraction(
- selectedItemName, target, interaction, _scene.state.roomName);
+ selectedItemName, target, interaction, _scene.executionContext());
if (!handled) {
debugC(3, kDebugRoom, "Harvester: item use miss selected='%s' target='%s'",
selectedItemName.c_str(), target.objectName.c_str());
@@ -310,7 +310,7 @@ Common::Error ItemInteractions::handleSelectedItemMiss(Interaction &interactionP
};
InteractionResult interaction;
_engine.getScript()->executeActionTag(responseTags[_engine.getRandomNumber(4)],
- interaction, true, _scene.state.roomName);
+ interaction, true, _scene.executionContext());
bool didTransition = false;
Common::Error interactionError =
interactionProcessor.handleInteractionResult(interaction, didTransition, getSelectedItemName());
@@ -399,7 +399,7 @@ Common::Error Interaction::runRegionInteraction(const RegionRecord ®ion,
InventorySystem &inventory, bool &needsRedraw) {
const RoomPlayerState &playerState = _player.getState();
InteractionResult interaction;
- if (!_engine.getScript()->resolveRegionInteraction(region, interaction, _scene.state.roomName))
+ if (!_engine.getScript()->resolveRegionInteraction(region, interaction, _scene.executionContext()))
return Common::kNoError;
debugC(2, kDebugRoom,
"Harvester: region interaction room='%s' region='%s' action='%s' player=(%d,%d,z=%.2f) next_room='%s'",
@@ -739,7 +739,7 @@ Common::Error Interaction::handleInteractionResult(const InteractionResult &inte
InteractionResult continuationInteraction;
if (_engine.getScript()->executeActionTag(
interaction.continuationTag, continuationInteraction, true,
- _scene.state.roomName)) {
+ _scene.executionContext())) {
Common::Error interactionError =
handleInteractionResult(continuationInteraction, didTransition, usedItemName, interruptPlayerMovement);
if (interactionError.getCode() != Common::kNoError)
@@ -763,7 +763,7 @@ Common::Error Interaction::runScriptedDialogue(const Common::String &npcName,
Common::Error dialogueError = _flow.runRoomNpcDialogue(
dialogueBackdrop, _scene.palette, _scene.targetPaletteBrightness,
- _scene.state.roomName, *dialogueNpc, usedItemName);
+ _scene.executionContext(), *dialogueNpc, usedItemName);
if (dialogueError.getCode() != Common::kNoError)
return dialogueError;
} else {
@@ -785,7 +785,7 @@ Common::Error Interaction::runScriptedDialogue(const Common::String &npcName,
if (!didTransition && !abortRemainingCommandChain && !continuationTag.empty()) {
InteractionResult continuationInteraction;
if (_engine.getScript()->executeActionTag(
- continuationTag, continuationInteraction, true, _scene.state.roomName)) {
+ continuationTag, continuationInteraction, true, _scene.executionContext())) {
Common::Error interactionError =
handleInteractionResult(continuationInteraction, didTransition, usedItemName);
if (interactionError.getCode() != Common::kNoError)
diff --git a/engines/harvester/npc/dialogue_runtime.h b/engines/harvester/npc/dialogue_runtime.h
index 50b7ce3cfa2..3c5d901d116 100644
--- a/engines/harvester/npc/dialogue_runtime.h
+++ b/engines/harvester/npc/dialogue_runtime.h
@@ -59,11 +59,11 @@ public:
typedef DialogueKeywordMenuSelectionState KeywordMenuSelectionState;
DialogueRuntime(HarvesterEngine &engine, Script &script, Text &text,
- Flow &flow, const Common::String ¤tRoomName,
+ Flow &flow, const ScriptExecutionContext &executionContext,
const Common::String &genericByeTopic,
DialogueRuntimeCallbacks &callbacks)
: _engine(engine), _script(script), _text(text),
- _flow(flow), _currentRoomName(currentRoomName),
+ _flow(flow), _executionContext(executionContext),
_genericByeTopic(genericByeTopic),
_callbacks(callbacks) {
}
@@ -72,11 +72,11 @@ public:
Script &startupScript() const { return _script; }
Text &startupText() const { return _text; }
Flow &startupFlow() const { return _flow; }
- const Common::String ¤tRoomName() const { return _currentRoomName; }
+ const Common::String ¤tRoomName() const { return _executionContext.roomName(); }
const Common::String &genericByeTopic() const { return _genericByeTopic; }
bool executeActionTag(const Common::String &tag, InteractionResult &result,
bool allowTransitions = true) const {
- return _script.executeActionTag(tag, result, allowTransitions, _currentRoomName);
+ return _script.executeActionTag(tag, result, allowTransitions, _executionContext);
}
void executeAndQueueAction(const Common::String &tag) const {
InteractionResult interaction;
@@ -140,7 +140,7 @@ private:
Script &_script;
Text &_text;
Flow &_flow;
- const Common::String &_currentRoomName;
+ const ScriptExecutionContext _executionContext;
const Common::String &_genericByeTopic;
DialogueRuntimeCallbacks &_callbacks;
mutable KeywordMenuSelectionState _lastKeywordSelection;
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index 9ba5b049b58..fc8c0d122fb 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -44,6 +44,9 @@ struct IndexedBitmap;
struct MenuTextConfig;
struct SceneState {
+ ScriptExecutionContext executionContext() const & { return ScriptExecutionContext(state.roomName); }
+ ScriptExecutionContext executionContext() const && = delete;
+
RoomSetupState state;
byte palette[256 * 3] = { 0 };
Common::Array<ObjectRecord> sceneObjects;
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index c917dc985b0..4029346fe1b 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -319,7 +319,7 @@ Common::Error Scene::runRoomExitCommands() {
InteractionResult continuationInteraction;
if (!_engine.getScript()->executeActionTag(
exitInteraction.continuationTag, continuationInteraction, false,
- _scene.state.roomName)) {
+ _scene.executionContext())) {
return Common::kNoError;
}
@@ -657,7 +657,7 @@ InputResult Scene::dispatchExpiredTimers(bool &needsRedraw) {
for (const Common::String &timerName : expiredTimerNames) {
InteractionResult timerInteraction;
if (!_engine.getScript()->executeTimerAction(
- timerName, timerInteraction, true, _scene.state.roomName))
+ timerName, timerInteraction, true, _scene.executionContext()))
continue;
bool didTransition = false;
diff --git a/engines/harvester/script.cpp b/engines/harvester/script.cpp
index de71ae5f6e5..763586eb59a 100644
--- a/engines/harvester/script.cpp
+++ b/engines/harvester/script.cpp
@@ -1735,7 +1735,8 @@ bool Script::executeRoomExitCommands(const Common::String &roomName,
}
bool Script::resolveObjectInteraction(const ObjectRecord &object, InteractionResult &result,
- const Common::String &roomName) {
+ const ScriptExecutionContext &executionContext) {
+ const Common::String &roomName = executionContext.roomName();
result = InteractionResult();
Common::String commandRoomName = roomName;
if (commandRoomName.empty() &&
@@ -1777,7 +1778,8 @@ bool Script::resolveObjectInteraction(const ObjectRecord &object, InteractionRes
}
bool Script::resolveRegionInteraction(const RegionRecord ®ion, InteractionResult &result,
- const Common::String &roomName) {
+ const ScriptExecutionContext &executionContext) {
+ const Common::String &roomName = executionContext.roomName();
result = InteractionResult();
if (region.actionTag.empty())
return false;
@@ -1800,7 +1802,8 @@ bool Script::resolveRegionInteraction(const RegionRecord ®ion, InteractionRes
}
bool Script::resolveUseItemInteraction(const Common::String &itemName, const ObjectRecord &target,
- InteractionResult &result, const Common::String &roomName) {
+ InteractionResult &result, const ScriptExecutionContext &executionContext) {
+ const Common::String &roomName = executionContext.roomName();
result = InteractionResult();
const UseItemRecord *useItem = findUseItemRecord(itemName, target);
@@ -1840,13 +1843,14 @@ bool Script::executeDebugCommand(const CommandRecord &command,
CommandRecord debugCommand = command;
debugCommand.triggerTag = debugTag;
_commands.push_back(Common::move(debugCommand));
- const bool handled = executeActionTag(debugTag, result, allowTransitions);
+ const bool handled = executeActionTag(debugTag, result, allowTransitions, ScriptExecutionContext());
_commands.pop_back();
return handled;
}
bool Script::executeActionTag(const Common::String &tag, InteractionResult &result,
- bool allowTransitions, const Common::String &roomName) {
+ bool allowTransitions, const ScriptExecutionContext &executionContext) {
+ const Common::String &roomName = executionContext.roomName();
result = InteractionResult();
if (tag.empty())
return false;
@@ -1869,7 +1873,8 @@ bool Script::executeActionTag(const Common::String &tag, InteractionResult &resu
}
bool Script::executeTimerAction(const Common::String &timerName, InteractionResult &result,
- bool allowTransitions, const Common::String &roomName) {
+ bool allowTransitions, const ScriptExecutionContext &executionContext) {
+ const Common::String &roomName = executionContext.roomName();
result = InteractionResult();
if (timerName.empty())
return false;
@@ -1904,7 +1909,7 @@ bool Script::executeTimerAction(const Common::String &timerName, InteractionResu
bool Script::executeNestedActionTag(const Common::String &tag, InteractionResult &result,
bool allowTransitions) {
- const bool handled = executeActionTag(tag, result, allowTransitions);
+ const bool handled = executeActionTag(tag, result, allowTransitions, ScriptExecutionContext());
if (handled)
result.abortRemainingCommandChain = true;
diff --git a/engines/harvester/script.h b/engines/harvester/script.h
index c3872803fae..0f6ade5c563 100644
--- a/engines/harvester/script.h
+++ b/engines/harvester/script.h
@@ -266,6 +266,30 @@ struct RoomSetupState {
Common::Array<AudioCommand> audioCommands;
};
+class ScriptExecutionContext {
+public:
+ ScriptExecutionContext() = default;
+
+ static ScriptExecutionContext forNpcDeath(const NpcRecord &npc) {
+ return ScriptExecutionContext(npc.roomName);
+ }
+ static ScriptExecutionContext forMonsterDeath(const MonsterRecord &monster) {
+ return ScriptExecutionContext(monster.roomName);
+ }
+
+ const Common::String &roomName() const {
+ static const Common::String noRoom;
+ return _roomName ? *_roomName : noRoom;
+ }
+
+private:
+ friend struct SceneState;
+
+ explicit ScriptExecutionContext(const Common::String &roomName) : _roomName(&roomName) {}
+
+ const Common::String *const _roomName = nullptr;
+};
+
enum StartupRoomTransitionKind {
kStartupRoomTransitionNone = 0,
kStartupRoomTransitionChangeRoom,
@@ -369,17 +393,17 @@ public:
bool executeRoomEnterCommands(const Common::String &roomName, InteractionResult &result);
bool executeRoomExitCommands(const Common::String &roomName, InteractionResult &result);
bool resolveObjectInteraction(const ObjectRecord &object, InteractionResult &result,
- const Common::String &roomName = Common::String());
+ const ScriptExecutionContext &executionContext);
bool resolveRegionInteraction(const RegionRecord ®ion, InteractionResult &result,
- const Common::String &roomName = Common::String());
+ const ScriptExecutionContext &executionContext);
bool resolveUseItemInteraction(const Common::String &itemName, const ObjectRecord &target,
- InteractionResult &result, const Common::String &roomName = Common::String());
+ InteractionResult &result, const ScriptExecutionContext &executionContext);
bool executeDebugCommand(const CommandRecord &command, InteractionResult &result,
bool allowTransitions = true);
bool executeActionTag(const Common::String &tag, InteractionResult &result,
- bool allowTransitions = true, const Common::String &roomName = Common::String());
+ bool allowTransitions, const ScriptExecutionContext &executionContext);
bool executeTimerAction(const Common::String &timerName, InteractionResult &result,
- bool allowTransitions = true, const Common::String &roomName = Common::String());
+ bool allowTransitions, const ScriptExecutionContext &executionContext);
bool executeNestedActionTag(const Common::String &tag, InteractionResult &result,
bool allowTransitions = true);
bool isPickupObject(const ObjectRecord &object) const;
Commit: 4c2cd50a791c3814cbaf2e8832d2543944ef0a08
https://github.com/scummvm/scummvm/commit/4c2cd50a791c3814cbaf2e8832d2543944ef0a08
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Move font lookup into Text
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/dialogue.cpp
engines/harvester/flow.cpp
engines/harvester/menu.cpp
engines/harvester/scene.cpp
engines/harvester/text.cpp
engines/harvester/text.h
diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index 17fb1e6b568..48b0992f189 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -207,19 +207,6 @@ static void syncDialogueSharedState(Common::Serializer &s, DialogueSharedState &
syncDialogueInt(s, state.dialogueStateD2f30);
}
-static const CftFontResource *findStartupFontByName(const HarvesterEngine &engine, const char *fontName) {
- const Text *text = engine.getText();
- if (!text || !fontName)
- return nullptr;
-
- for (const CftFontResource &font : text->getFonts()) {
- if (font.name.equalsIgnoreCase(fontName))
- return &font;
- }
-
- return nullptr;
-}
-
static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
if (!bitmap.isValid())
return;
@@ -435,12 +422,12 @@ public:
return;
}
- if (const CftFontResource *subtitleFontResource = findStartupFontByName(_engine, "TEXTFONT")) {
+ if (const CftFontResource *subtitleFontResource = _text->findFont("TEXTFONT")) {
_subtitleCftFont.reset(new HarvesterCftFont(*subtitleFontResource));
if (!_subtitleCftFont->isValid())
_subtitleCftFont.reset();
}
- if (const CftFontResource *menuFontResource = findStartupFontByName(_engine, "TEXTFNT2")) {
+ if (const CftFontResource *menuFontResource = _text->findFont("TEXTFNT2")) {
_menuCftFont.reset(new HarvesterCftFont(*menuFontResource));
if (!_menuCftFont->isValid())
_menuCftFont.reset();
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 6bb61ba9653..359d826ffc0 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -120,19 +120,6 @@ static const int kCursorSequenceTransition = 6;
static const int kCursorSequenceNeutral = 7;
} // End of anonymous namespace
-static const CftFontResource *findStartupFontByName(const HarvesterEngine &engine, const char *fontName) {
- const Text *text = engine.getText();
- if (!text || !fontName)
- return nullptr;
-
- for (const CftFontResource &font : text->getFonts()) {
- if (font.name.equalsIgnoreCase(fontName))
- return &font;
- }
-
- return nullptr;
-}
-
static byte findNearestPaletteColor(const byte *palette, byte red, byte green, byte blue) {
if (!palette)
return 0;
@@ -1639,7 +1626,8 @@ Common::Error Flow::runDemoIntroduction() {
ResourceManager *resources = _engine.getResources();
EntityManager *entityManager = _engine.getRuntimeEntities();
const Art *art = _engine.getArt();
- const CftFontResource *fontResource = findStartupFontByName(_engine, "TEXTFONT");
+ const Text *text = _engine.getText();
+ const CftFontResource *fontResource = text ? text->findFont("TEXTFONT") : nullptr;
if (!screen || !resources || !art || !fontResource)
return Common::kReadingFailed;
@@ -1768,7 +1756,8 @@ Common::Error Flow::runTownMapSelector(const Common::String &mapEntryName,
Graphics::Screen *screen = _engine.getScreen();
const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
Common::ScopedPtr<HarvesterCftFont> townMapFont;
- if (const CftFontResource *townMapFontResource = findStartupFontByName(_engine, "TEXTFONT")) {
+ const Text *text = _engine.getText();
+ if (const CftFontResource *townMapFontResource = text ? text->findFont("TEXTFONT") : nullptr) {
townMapFont.reset(new HarvesterCftFont(*townMapFontResource));
if (townMapFont->isValid())
font = townMapFont.get();
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index 0e83333470b..7c6c1f8e91c 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -182,19 +182,6 @@ private:
static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y);
static int getNativeRoomMenuLineHeight(const Graphics::Font &selectedFont);
-static const CftFontResource *findStartupFontByName(const HarvesterEngine &engine, const char *fontName) {
- const Text *text = engine.getText();
- if (!text || !fontName)
- return nullptr;
-
- for (const CftFontResource &font : text->getFonts()) {
- if (font.name.equalsIgnoreCase(fontName))
- return &font;
- }
-
- return nullptr;
-}
-
static int clampStartupOptionLevel(int level) {
if (level < 0)
return 0;
@@ -1494,8 +1481,9 @@ Common::Error MenuSystem::runSaveSlotMenu(Flow &flow, SaveLoadMode mode, bool &c
completed = false;
ResourceManager *resources = _engine.getResources();
MetaEngine *metaEngine = _engine.getMetaEngine();
- const CftFontResource *slotNameFontResource = findStartupFontByName(_engine, "MEDFONT1");
- const CftFontResource *slotLabelFontResource = findStartupFontByName(_engine, "MEDFONT2");
+ const Text *text = _engine.getText();
+ const CftFontResource *slotNameFontResource = text ? text->findFont("MEDFONT1") : nullptr;
+ const CftFontResource *slotLabelFontResource = text ? text->findFont("MEDFONT2") : nullptr;
if (!resources || !metaEngine || !slotNameFontResource || !slotLabelFontResource)
return Common::kReadingFailed;
if (mode == kSaveMode ? !_engine.canSaveGameStateCurrently() : !_engine.canLoadGameStateCurrently())
@@ -1662,8 +1650,9 @@ Common::Error MenuSystem::runConfirmPrompt(const IndexedBitmap &backdrop, const
float paletteBrightness, Flow &flow, const Common::String &promptText,
bool &confirmed) {
const Art *art = _engine.getArt();
- const CftFontResource *promptFontResource = findStartupFontByName(_engine, "MEDFONT1");
- const CftFontResource *choiceFontResource = findStartupFontByName(_engine, "MEDFONT2");
+ const Text *text = _engine.getText();
+ const CftFontResource *promptFontResource = text ? text->findFont("MEDFONT1") : nullptr;
+ const CftFontResource *choiceFontResource = text ? text->findFont("MEDFONT2") : nullptr;
if (!art || !promptFontResource || !choiceFontResource)
return Common::kReadingFailed;
@@ -1762,8 +1751,9 @@ Common::Error MenuSystem::runPasswordPrompt(const IndexedBitmap &backdrop, const
float paletteBrightness, Flow &flow, bool drawLogo, Common::String &password,
bool &accepted) const {
const Art *art = _engine.getArt();
- const CftFontResource *titleFontResource = findStartupFontByName(_engine, "HARVFONT");
- const CftFontResource *entryFontResource = findStartupFontByName(_engine, "HARVFNT2");
+ const Text *text = _engine.getText();
+ const CftFontResource *titleFontResource = text ? text->findFont("HARVFONT") : nullptr;
+ const CftFontResource *entryFontResource = text ? text->findFont("HARVFNT2") : nullptr;
if (!art || !titleFontResource || !entryFontResource)
return Common::kReadingFailed;
@@ -1881,8 +1871,9 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
const Art *art = _engine.getArt();
Script *script = _engine.getScript();
ResourceManager *resources = _engine.getResources();
- const CftFontResource *selectedFontResource = findStartupFontByName(_engine, "HARVFONT");
- const CftFontResource *unselectedFontResource = findStartupFontByName(_engine, "HARVFNT2");
+ const Text *text = _engine.getText();
+ const CftFontResource *selectedFontResource = text ? text->findFont("HARVFONT") : nullptr;
+ const CftFontResource *unselectedFontResource = text ? text->findFont("HARVFNT2") : nullptr;
if (!art || !script || !resources || !selectedFontResource || !unselectedFontResource)
return Common::kReadingFailed;
@@ -2333,8 +2324,9 @@ void MenuSystem::renderBackdropMenuScreen(const IndexedBitmap &backdrop, const b
int selectedItem) const {
Graphics::Screen *screen = _engine.getScreen();
const Art *art = _engine.getArt();
- const CftFontResource *selectedFontResource = findStartupFontByName(_engine, "HARVFONT");
- const CftFontResource *unselectedFontResource = findStartupFontByName(_engine, "HARVFNT2");
+ const Text *text = _engine.getText();
+ const CftFontResource *selectedFontResource = text ? text->findFont("HARVFONT") : nullptr;
+ const CftFontResource *unselectedFontResource = text ? text->findFont("HARVFNT2") : nullptr;
if (!screen || !art || !selectedFontResource || !unselectedFontResource || !backdrop.isValid())
return;
@@ -2384,7 +2376,8 @@ int MenuSystem::getMenuItemAt(const Common::Point &mousePos,
int MenuSystem::getBackdropMenuItemAt(const Common::Point &mousePos,
const Common::Array<Common::String> &menuItems) const {
- const CftFontResource *selectedFontResource = findStartupFontByName(_engine, "HARVFONT");
+ const Text *text = _engine.getText();
+ const CftFontResource *selectedFontResource = text ? text->findFont("HARVFONT") : nullptr;
if (!selectedFontResource)
return getMenuItemAt(mousePos, menuItems);
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index 4029346fe1b..d90da2d6beb 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -891,19 +891,6 @@ Common::Error Scene::killDebugActiveMonster(const Common::Point &mousePos, bool
return _combat.killDebugActiveMonster(mousePos, needsRedraw);
}
-static const CftFontResource *findStartupFontByName(const HarvesterEngine &engine, const char *fontName) {
- const Text *text = engine.getText();
- if (!text || !fontName)
- return nullptr;
-
- for (const CftFontResource &font : text->getFonts()) {
- if (font.name.equalsIgnoreCase(fontName))
- return &font;
- }
-
- return nullptr;
-}
-
SceneRunner::SceneRunner(HarvesterEngine &engine,
InventorySystem &inventory, CheatSystem &cheats)
: _engine(engine), _inventory(inventory), _cheats(cheats) {
@@ -995,8 +982,9 @@ Common::Error SceneRunner::runRoomLoop(Flow &flow, const Common::String &targetN
Graphics::Screen *screen = _engine.getScreen();
const Art *art = _engine.getArt();
const Graphics::Font *bodyFont = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
- const CftFontResource *promptFontResource = findStartupFontByName(_engine, "MEDFONT1");
- const CftFontResource *inventoryTooltipFontResource = findStartupFontByName(_engine, "TEXTFONT");
+ const Text *text = _engine.getText();
+ const CftFontResource *promptFontResource = text ? text->findFont("MEDFONT1") : nullptr;
+ const CftFontResource *inventoryTooltipFontResource = text ? text->findFont("TEXTFONT") : nullptr;
Common::ScopedPtr<HarvesterCftFont> promptCftFont;
Common::ScopedPtr<HarvesterCftFont> inventoryTooltipCftFont;
const Graphics::Font *promptFont = bodyFont;
diff --git a/engines/harvester/text.cpp b/engines/harvester/text.cpp
index dffc9693187..f295f06117e 100644
--- a/engines/harvester/text.cpp
+++ b/engines/harvester/text.cpp
@@ -277,6 +277,18 @@ void Text::decodeXorText(Common::Array<byte> &data) const {
}
}
+const CftFontResource *Text::findFont(const char *fontName) const {
+ if (!fontName)
+ return nullptr;
+
+ for (const CftFontResource &font : _fonts) {
+ if (font.name.equalsIgnoreCase(fontName))
+ return &font;
+ }
+
+ return nullptr;
+}
+
bool Text::resolveDialogueSubtitle(int wavId, Common::String &text) const {
text.clear();
if (wavId <= 0 || _dialogueEntries.empty() || _dialogueData.empty())
diff --git a/engines/harvester/text.h b/engines/harvester/text.h
index 3d64d0879ba..e72c2c75778 100644
--- a/engines/harvester/text.h
+++ b/engines/harvester/text.h
@@ -59,7 +59,7 @@ public:
const Common::Array<byte> &getDialogueData() const { return _dialogueData; }
const Common::Array<DialogueIndexEntry> &getDialogueEntries() const { return _dialogueEntries; }
const Common::Array<Common::String> &getDialogueResponseLines() const { return _dialogueResponseLines; }
- const Common::Array<CftFontResource> &getFonts() const { return _fonts; }
+ const CftFontResource *findFont(const char *fontName) const;
bool resolveDialogueSubtitle(int wavId, Common::String &text) const;
Common::String getDialogueResponseLine(int zeroBasedIndex) const;
Commit: 736efc4b9db42c063e2ee433596caaa46fc381c8
https://github.com/scummvm/scummvm/commit/736efc4b9db42c063e2ee433596caaa46fc381c8
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Move scene drawing into RoomPresentation
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.cpp
engines/harvester/input.cpp
engines/harvester/room_presentation.cpp
engines/harvester/room_presentation.h
engines/harvester/room_support.h
engines/harvester/scene.cpp
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 359d826ffc0..b9de7ecbd8d 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -43,6 +43,7 @@
#include "harvester/resources.h"
#include "harvester/entity.h"
#include "harvester/scene_entities.h"
+#include "harvester/room_presentation.h"
#include "harvester/art.h"
#include "harvester/monster.h"
#include "harvester/player.h"
@@ -104,12 +105,6 @@ static const int kTownMapCursorHitExtent = 5;
static const byte kIdentTextColor = 0xd3;
static const byte kShadowColor = 0;
static const byte kTownMapLabelColor = 0x28;
-static const int kRoomDebugLabelPaddingX = 3;
-static const int kRoomDebugLabelPaddingY = 2;
-static const int kRoomDebugRoomNameX = 4;
-static const int kRoomDebugRoomNameY = 4;
-static const int kTimerDebugOverlayXDivisor = 8;
-static const int kTimerDebugOverlayLineSpacing = 1;
static const int kCursorSequenceWalk = 0;
static const int kCursorSequenceExamine = 1;
@@ -120,294 +115,6 @@ static const int kCursorSequenceTransition = 6;
static const int kCursorSequenceNeutral = 7;
} // End of anonymous namespace
-static byte findNearestPaletteColor(const byte *palette, byte red, byte green, byte blue) {
- if (!palette)
- return 0;
-
- byte bestIndex = 0;
- uint32 bestDistance = 0xffffffffu;
- for (int i = 0; i < 256; ++i) {
- const int paletteOffset = i * 3;
- const int dr = (int)palette[paletteOffset] - red;
- const int dg = (int)palette[paletteOffset + 1] - green;
- const int db = (int)palette[paletteOffset + 2] - blue;
- const uint32 distance = (uint32)(dr * dr + dg * dg + db * db);
- if (distance < bestDistance) {
- bestDistance = distance;
- bestIndex = (byte)i;
- }
- }
-
- return bestIndex;
-}
-
-static Common::String resolveRoomDebugObjectLabel(HarvesterEngine &engine, const ObjectRecord &object) {
- if (Script *script = engine.getScript()) {
- const Common::String resolvedLabel = script->resolveObjectLabel(object);
- if (!resolvedLabel.empty())
- return resolvedLabel;
- }
-
- return object.objectName;
-}
-
-static Common::String resolveRoomDebugNpcLabel(const NpcRecord &npc) {
- Common::String label = !npc.entityInitArg.empty() ? npc.entityInitArg : npc.npcName;
- for (uint i = 0; i < label.size(); ++i) {
- if (label[i] == '_')
- label.setChar(' ', i);
- }
-
- return label;
-}
-
-static Common::String resolveCombatDebugLabel(const Common::String &name, int currentHitPoints, int maxHitPoints) {
- Common::String label = name;
- for (uint i = 0; i < label.size(); ++i) {
- if (label[i] == '_')
- label.setChar(' ', i);
- }
-
- return Common::String::format("%s (%d/%d)", label.c_str(), currentHitPoints, maxHitPoints);
-}
-
-static void drawRoomDebugLabel(Graphics::Screen &screen, const Graphics::Font &font,
- const Common::String &text, int x, int y, byte textColor, byte backgroundColor) {
- if (text.empty())
- return;
-
- const int labelWidth = font.getStringWidth(text) + kRoomDebugLabelPaddingX * 2;
- const int labelHeight = font.getFontHeight() + kRoomDebugLabelPaddingY * 2;
- const int drawX = CLIP<int>(x, 0, MAX(0, screen.w - labelWidth));
- const int drawY = CLIP<int>(y, 0, MAX(0, screen.h - labelHeight));
- const Common::Rect background(drawX, drawY,
- MIN<int>(screen.w, drawX + labelWidth), MIN<int>(screen.h, drawY + labelHeight));
- screen.fillRect(background, backgroundColor);
- font.drawString(&screen, text,
- background.left + kRoomDebugLabelPaddingX,
- background.top + kRoomDebugLabelPaddingY,
- MAX(0, background.width() - kRoomDebugLabelPaddingX * 2),
- textColor);
-}
-
-static void drawRoomDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
- const SceneState &scene) {
- if (!engine.isRoomDebugEnabled())
- return;
-
- const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
- if (!font)
- return;
-
- byte displayPalette[256 * 3];
- screen.getPalette(displayPalette);
- const byte black = findNearestPaletteColor(displayPalette, 0x00, 0x00, 0x00);
- const byte white = findNearestPaletteColor(displayPalette, 0xff, 0xff, 0xff);
- const byte darkGray = findNearestPaletteColor(displayPalette, 0x40, 0x40, 0x40);
- const byte red = findNearestPaletteColor(displayPalette, 0xff, 0x00, 0x00);
- Common::String roomName = scene.state.roomName;
- roomName.toUppercase();
-
- drawRoomDebugLabel(screen, *font, roomName,
- kRoomDebugRoomNameX, kRoomDebugRoomNameY, black, white);
-
- for (const RegionRecord ®ion : scene.sceneRegions)
- drawRoomDebugLabel(screen, *font, region.regionName, region.left, region.top, white, darkGray);
-
- EntityManager *entityManager = engine.getRuntimeEntities();
- for (const ObjectRecord &object : scene.sceneObjects) {
- const Entity *entity = entityManager
- ? entityManager->findSceneEntityByName(object.objectName)
- : nullptr;
- if (entity && entity->getClassId() == kEntityClassBackground)
- continue;
-
- drawRoomDebugLabel(screen, *font, resolveRoomDebugObjectLabel(engine, object),
- object.currentX, object.currentY, white, black);
- }
-
- for (const NpcRecord &npc : scene.state.roomNpcs) {
- const Entity *entity = entityManager
- ? entityManager->findSceneEntityByName(npc.npcName)
- : nullptr;
- if (!entity || entity->getClassId() != kEntityClassNpc || !entity->isVisible())
- continue;
-
- const Common::Rect npcRect = entity->getScreenRect();
- drawRoomDebugLabel(screen, *font, resolveRoomDebugNpcLabel(npc),
- npcRect.left, npcRect.top, white, red);
- }
-}
-
-static void drawCombatDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
- const SceneState &scene) {
- if (!engine.isCombatDebugEnabled())
- return;
-
- const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
- EntityManager *entityManager = engine.getRuntimeEntities();
- Script *script = engine.getScript();
- if (!font || !entityManager)
- return;
-
- byte displayPalette[256 * 3];
- screen.getPalette(displayPalette);
- const byte black = findNearestPaletteColor(displayPalette, 0x00, 0x00, 0x00);
- const byte white = findNearestPaletteColor(displayPalette, 0xff, 0xff, 0xff);
- const byte red = findNearestPaletteColor(displayPalette, 0xff, 0x00, 0x00);
-
- const Entity *playerEntity = entityManager->findSceneEntityByName(kPlayerActorEntityName);
- if (script && playerEntity &&
- playerEntity->getClassId() == kEntityClassPlayer &&
- playerEntity->isVisible()) {
- const Common::Rect playerRect = playerEntity->getScreenRect();
- drawRoomDebugLabel(screen, *font,
- resolveCombatDebugLabel(playerEntity->getName(),
- script->getPlayerCurrentHitPoints(), Script::kDefaultPlayerHitPoints),
- playerRect.left, playerRect.top, white, red);
- }
-
- for (const MonsterRecord &monster : scene.state.roomMonsters) {
- const Entity *entity = entityManager->findSceneEntityByName(monster.monsterName);
- if (!entity || entity->getClassId() != kEntityClassMonster || !entity->isVisible())
- continue;
-
- const Common::Rect monsterRect = entity->getScreenRect();
- drawRoomDebugLabel(screen, *font,
- resolveCombatDebugLabel(monster.monsterName,
- monster.currentHitPoints, monster.initialHitPoints),
- monsterRect.left, monsterRect.top, white, black);
- }
-}
-
-static Common::Rect getPathfindingMovementBounds(const Graphics::Screen &screen,
- const RoomSetupState &state) {
- if (!Player::supportsMovementBand(state))
- return Common::Rect();
-
- return Common::Rect(0, state.roomMaxZScreenY, screen.w, state.roomMinZScreenY + 1);
-}
-
-static void drawClippedDebugFrame(Graphics::Screen &screen, Common::Rect rect, byte color) {
- rect.clip(screen.getBounds());
- if (rect.isEmpty())
- return;
-
- screen.frameRect(rect, color);
-}
-
-static bool canEntityAffectPlayerPathfinding(const Entity &entity) {
- if (!entity.isVisible())
- return false;
-
- switch (entity.getClassId()) {
- case kEntityClassCursor:
- case kEntityClassBackground:
- case kEntityClassPlayer:
- case kEntityClassRectHotspot:
- case kEntityClassRectHotspot19:
- case kEntityClassTimer:
- return false;
- default:
- break;
- }
-
- return entity.getClassId() == kEntityClassDisabledHotspot || entity.hasFrames();
-}
-
-static void drawPathfindingBlockerOutline(Graphics::Screen &screen, EntityManager &entityManager,
- const Common::String &entityName, const Common::Rect &movementBounds, byte color) {
- const Entity *entity = entityManager.findSceneEntityByName(entityName);
- if (!entity || !canEntityAffectPlayerPathfinding(*entity))
- return;
-
- Common::Rect rect = entity->getScreenRect();
- if (rect.isEmpty())
- return;
-
- Common::Rect overlap = rect;
- overlap.clip(movementBounds);
- if (overlap.isEmpty())
- return;
-
- drawClippedDebugFrame(screen, rect, color);
-}
-
-static void drawPathfindingDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
- const SceneState &scene) {
- if (!engine.isPathfindingDebugEnabled())
- return;
-
- byte displayPalette[256 * 3];
- screen.getPalette(displayPalette);
- const byte blue = findNearestPaletteColor(displayPalette, 0x00, 0x40, 0xff);
- const byte green = findNearestPaletteColor(displayPalette, 0x00, 0xff, 0x00);
- const Common::Rect movementBounds = getPathfindingMovementBounds(screen, scene.state);
- if (movementBounds.isEmpty())
- return;
-
- drawClippedDebugFrame(screen, movementBounds, blue);
-
- EntityManager *entityManager = engine.getRuntimeEntities();
- if (!entityManager)
- return;
-
- for (const ObjectRecord &object : scene.sceneObjects)
- drawPathfindingBlockerOutline(screen, *entityManager,
- object.objectName, movementBounds, green);
-
- for (const AnimRecord &anim : scene.sceneAnimations)
- drawPathfindingBlockerOutline(screen, *entityManager,
- anim.animName, movementBounds, green);
-}
-
-static Common::String resolveTimerDebugLabel(const TimerRecord &timer, const Entity &entity) {
- const Common::String actionTag = timer.arg2.empty() ? Common::String("<none>") : timer.arg2;
-
- return Common::String::format("%s start=%d current=%d action=%s",
- timer.timerName.c_str(), entity.getTimerInitialValue(),
- entity.getTimerCurrentValue(), actionTag.c_str());
-}
-
-static void drawTimerDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
- const SceneState &) {
- if (!engine.isTimerDebugEnabled())
- return;
-
- const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
- EntityManager *entityManager = engine.getRuntimeEntities();
- Script *script = engine.getScript();
- if (!font || !entityManager || !script)
- return;
-
- Common::Array<Common::String> labels;
- for (const TimerRecord &timer : script->getTimers()) {
- const Entity *entity = entityManager->findSceneEntityByName(timer.timerName);
- if (!entity || entity->getClassId() != kEntityClassTimer || !entity->isTimerEnabled())
- continue;
-
- const TimerRecord *runtimeTimer = script->findRuntimeTimerRecord(timer.timerName);
- labels.push_back(resolveTimerDebugLabel(runtimeTimer ? *runtimeTimer : timer, *entity));
- }
- if (labels.empty())
- return;
-
- byte displayPalette[256 * 3];
- screen.getPalette(displayPalette);
- const byte black = findNearestPaletteColor(displayPalette, 0x00, 0x00, 0x00);
- const byte white = findNearestPaletteColor(displayPalette, 0xff, 0xff, 0xff);
-
- const int labelHeight = font->getFontHeight() + kRoomDebugLabelPaddingY * 2;
- const int lineHeight = labelHeight + kTimerDebugOverlayLineSpacing;
- const int totalHeight = (int)labels.size() * labelHeight +
- (int)(labels.size() - 1) * kTimerDebugOverlayLineSpacing;
- const int x = screen.w / kTimerDebugOverlayXDivisor;
- const int y = CLIP<int>((screen.h - totalHeight) / 2, 0, MAX(0, screen.h - totalHeight));
-
- for (uint i = 0; i < labels.size(); ++i)
- drawRoomDebugLabel(screen, *font, labels[i], x, y + (int)i * lineHeight, white, black);
-}
-
static int clampTownMapPanelIndex(int panelIndex) {
return CLIP<int>(panelIndex, 0, ARRAYSIZE(kTownMapBitmapPaths) - 1);
}
@@ -760,18 +467,6 @@ bool shouldRunStartupRoomProbe() {
ConfMan.getBool("harvester_debug_probe_startup_room");
}
-void drawRoomScene(HarvesterEngine &engine, Graphics::Screen &screen, const SceneState &scene,
- float brightness) {
- setScaledPalette(screen, scene.palette, brightness);
- screen.fillRect(screen.getBounds(), 0);
- if (engine.getRuntimeEntities())
- engine.getRuntimeEntities()->drawSceneEntities(screen);
- drawRoomDebugOverlay(engine, screen, scene);
- drawCombatDebugOverlay(engine, screen, scene);
- drawPathfindingDebugOverlay(engine, screen, scene);
- drawTimerDebugOverlay(engine, screen, scene);
-}
-
const ObjectRecord *findSceneObjectByName(const Common::Array<ObjectRecord> &objects,
const Common::String &objectName) {
for (const ObjectRecord &object : objects) {
@@ -1296,7 +991,7 @@ static void renderQuickTipsScreen(HarvesterEngine &engine, const SceneState &sce
if (!screen)
return;
- drawRoomScene(engine, *screen, scene, scene.targetPaletteBrightness);
+ RoomPresentation::drawRoomScene(engine, *screen, scene, scene.targetPaletteBrightness);
drawQuickTipsPanel(engine, config, layout, tipText);
if (engine.getRuntimeEntities())
@@ -1475,7 +1170,7 @@ Common::Error Flow::runQuickTips() {
return transitionError;
logScenePaletteSummary("quick tips scene palette", scene, kPaletteBrightnessBlack);
- drawRoomScene(_engine, *screen, scene, kPaletteBrightnessBlack);
+ RoomPresentation::drawRoomScene(_engine, *screen, scene, kPaletteBrightnessBlack);
screen->makeAllDirty();
screen->update();
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index abe6160033b..8dfd90ec864 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -721,7 +721,7 @@ InputResult Input::handleKeyDown(const Common::KeyState &key, bool &needsRedraw)
if (!activeScreen)
return InputResult::leaveRoom(Common::kNoError);
IndexedBitmap roomMenuBackdrop;
- drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
+ RoomPresentation::drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
if (!captureScreenBackdrop(*activeScreen, roomMenuBackdrop))
return InputResult::leaveRoom(Common::kReadingFailed);
Common::Error menuError = _flow.runRoomMenu(
diff --git a/engines/harvester/room_presentation.cpp b/engines/harvester/room_presentation.cpp
index 024c15148c6..1807e9f44f0 100644
--- a/engines/harvester/room_presentation.cpp
+++ b/engines/harvester/room_presentation.cpp
@@ -26,12 +26,16 @@
#include "common/events.h"
#include "common/system.h"
#include "common/textconsole.h"
+#include "graphics/font.h"
+#include "graphics/fontman.h"
#include "graphics/framelimiter.h"
#include "harvester/art.h"
#include "harvester/detection.h"
+#include "harvester/entity.h"
#include "harvester/flow.h"
#include "harvester/harvester.h"
#include "harvester/palette_utils.h"
+#include "harvester/player.h"
#include "harvester/resources.h"
#include "harvester/room_support.h"
@@ -39,6 +43,13 @@ namespace Harvester {
static const float kNormalPaletteBrightness = 1.0f;
static const float kDimPaletteBrightness = 0.6f;
+static const char *const kPlayerActorEntityName = "PLAYER";
+static const int kRoomDebugLabelPaddingX = 3;
+static const int kRoomDebugLabelPaddingY = 2;
+static const int kRoomDebugRoomNameX = 4;
+static const int kRoomDebugRoomNameY = 4;
+static const int kTimerDebugOverlayXDivisor = 8;
+static const int kTimerDebugOverlayLineSpacing = 1;
static bool loadPaletteResource(ResourceManager &resources, const Common::String &path, byte *palette) {
Common::Array<byte> data;
@@ -56,6 +67,306 @@ static void setScaledRoomPalette(Graphics::Screen &screen, const byte *palette,
screen.setPalette(scaledPalette);
}
+static byte findNearestPaletteColor(const byte *palette, byte red, byte green, byte blue) {
+ if (!palette)
+ return 0;
+
+ byte bestIndex = 0;
+ uint32 bestDistance = 0xffffffffu;
+ for (int i = 0; i < 256; ++i) {
+ const int paletteOffset = i * 3;
+ const int dr = (int)palette[paletteOffset] - red;
+ const int dg = (int)palette[paletteOffset + 1] - green;
+ const int db = (int)palette[paletteOffset + 2] - blue;
+ const uint32 distance = (uint32)(dr * dr + dg * dg + db * db);
+ if (distance < bestDistance) {
+ bestDistance = distance;
+ bestIndex = (byte)i;
+ }
+ }
+
+ return bestIndex;
+}
+
+static Common::String resolveRoomDebugObjectLabel(HarvesterEngine &engine, const ObjectRecord &object) {
+ if (Script *script = engine.getScript()) {
+ const Common::String resolvedLabel = script->resolveObjectLabel(object);
+ if (!resolvedLabel.empty())
+ return resolvedLabel;
+ }
+
+ return object.objectName;
+}
+
+static Common::String resolveRoomDebugNpcLabel(const NpcRecord &npc) {
+ Common::String label = !npc.entityInitArg.empty() ? npc.entityInitArg : npc.npcName;
+ for (uint i = 0; i < label.size(); ++i) {
+ if (label[i] == '_')
+ label.setChar(' ', i);
+ }
+
+ return label;
+}
+
+static Common::String resolveCombatDebugLabel(const Common::String &name, int currentHitPoints, int maxHitPoints) {
+ Common::String label = name;
+ for (uint i = 0; i < label.size(); ++i) {
+ if (label[i] == '_')
+ label.setChar(' ', i);
+ }
+
+ return Common::String::format("%s (%d/%d)", label.c_str(), currentHitPoints, maxHitPoints);
+}
+
+static void drawRoomDebugLabel(Graphics::Screen &screen, const Graphics::Font &font,
+ const Common::String &text, int x, int y, byte textColor, byte backgroundColor) {
+ if (text.empty())
+ return;
+
+ const int labelWidth = font.getStringWidth(text) + kRoomDebugLabelPaddingX * 2;
+ const int labelHeight = font.getFontHeight() + kRoomDebugLabelPaddingY * 2;
+ const int drawX = CLIP<int>(x, 0, MAX(0, screen.w - labelWidth));
+ const int drawY = CLIP<int>(y, 0, MAX(0, screen.h - labelHeight));
+ const Common::Rect background(drawX, drawY,
+ MIN<int>(screen.w, drawX + labelWidth), MIN<int>(screen.h, drawY + labelHeight));
+ screen.fillRect(background, backgroundColor);
+ font.drawString(&screen, text,
+ background.left + kRoomDebugLabelPaddingX,
+ background.top + kRoomDebugLabelPaddingY,
+ MAX(0, background.width() - kRoomDebugLabelPaddingX * 2),
+ textColor);
+}
+
+static void drawRoomDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
+ const SceneState &scene) {
+ if (!engine.isRoomDebugEnabled())
+ return;
+
+ const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+ if (!font)
+ return;
+
+ byte displayPalette[256 * 3];
+ screen.getPalette(displayPalette);
+ const byte black = findNearestPaletteColor(displayPalette, 0x00, 0x00, 0x00);
+ const byte white = findNearestPaletteColor(displayPalette, 0xff, 0xff, 0xff);
+ const byte darkGray = findNearestPaletteColor(displayPalette, 0x40, 0x40, 0x40);
+ const byte red = findNearestPaletteColor(displayPalette, 0xff, 0x00, 0x00);
+ Common::String roomName = scene.state.roomName;
+ roomName.toUppercase();
+
+ drawRoomDebugLabel(screen, *font, roomName,
+ kRoomDebugRoomNameX, kRoomDebugRoomNameY, black, white);
+
+ for (const RegionRecord ®ion : scene.sceneRegions)
+ drawRoomDebugLabel(screen, *font, region.regionName, region.left, region.top, white, darkGray);
+
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ for (const ObjectRecord &object : scene.sceneObjects) {
+ const Entity *entity = entityManager
+ ? entityManager->findSceneEntityByName(object.objectName)
+ : nullptr;
+ if (entity && entity->getClassId() == kEntityClassBackground)
+ continue;
+
+ drawRoomDebugLabel(screen, *font, resolveRoomDebugObjectLabel(engine, object),
+ object.currentX, object.currentY, white, black);
+ }
+
+ for (const NpcRecord &npc : scene.state.roomNpcs) {
+ const Entity *entity = entityManager
+ ? entityManager->findSceneEntityByName(npc.npcName)
+ : nullptr;
+ if (!entity || entity->getClassId() != kEntityClassNpc || !entity->isVisible())
+ continue;
+
+ const Common::Rect npcRect = entity->getScreenRect();
+ drawRoomDebugLabel(screen, *font, resolveRoomDebugNpcLabel(npc),
+ npcRect.left, npcRect.top, white, red);
+ }
+}
+
+static void drawCombatDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
+ const SceneState &scene) {
+ if (!engine.isCombatDebugEnabled())
+ return;
+
+ const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ Script *script = engine.getScript();
+ if (!font || !entityManager)
+ return;
+
+ byte displayPalette[256 * 3];
+ screen.getPalette(displayPalette);
+ const byte black = findNearestPaletteColor(displayPalette, 0x00, 0x00, 0x00);
+ const byte white = findNearestPaletteColor(displayPalette, 0xff, 0xff, 0xff);
+ const byte red = findNearestPaletteColor(displayPalette, 0xff, 0x00, 0x00);
+
+ const Entity *playerEntity = entityManager->findSceneEntityByName(kPlayerActorEntityName);
+ if (script && playerEntity &&
+ playerEntity->getClassId() == kEntityClassPlayer &&
+ playerEntity->isVisible()) {
+ const Common::Rect playerRect = playerEntity->getScreenRect();
+ drawRoomDebugLabel(screen, *font,
+ resolveCombatDebugLabel(playerEntity->getName(),
+ script->getPlayerCurrentHitPoints(), Script::kDefaultPlayerHitPoints),
+ playerRect.left, playerRect.top, white, red);
+ }
+
+ for (const MonsterRecord &monster : scene.state.roomMonsters) {
+ const Entity *entity = entityManager->findSceneEntityByName(monster.monsterName);
+ if (!entity || entity->getClassId() != kEntityClassMonster || !entity->isVisible())
+ continue;
+
+ const Common::Rect monsterRect = entity->getScreenRect();
+ drawRoomDebugLabel(screen, *font,
+ resolveCombatDebugLabel(monster.monsterName,
+ monster.currentHitPoints, monster.initialHitPoints),
+ monsterRect.left, monsterRect.top, white, black);
+ }
+}
+
+static Common::Rect getPathfindingMovementBounds(const Graphics::Screen &screen,
+ const RoomSetupState &state) {
+ if (!Player::supportsMovementBand(state))
+ return Common::Rect();
+
+ return Common::Rect(0, state.roomMaxZScreenY, screen.w, state.roomMinZScreenY + 1);
+}
+
+static void drawClippedDebugFrame(Graphics::Screen &screen, Common::Rect rect, byte color) {
+ rect.clip(screen.getBounds());
+ if (rect.isEmpty())
+ return;
+
+ screen.frameRect(rect, color);
+}
+
+static bool canEntityAffectPlayerPathfinding(const Entity &entity) {
+ if (!entity.isVisible())
+ return false;
+
+ switch (entity.getClassId()) {
+ case kEntityClassCursor:
+ case kEntityClassBackground:
+ case kEntityClassPlayer:
+ case kEntityClassRectHotspot:
+ case kEntityClassRectHotspot19:
+ case kEntityClassTimer:
+ return false;
+ default:
+ break;
+ }
+
+ return entity.getClassId() == kEntityClassDisabledHotspot || entity.hasFrames();
+}
+
+static void drawPathfindingBlockerOutline(Graphics::Screen &screen, EntityManager &entityManager,
+ const Common::String &entityName, const Common::Rect &movementBounds, byte color) {
+ const Entity *entity = entityManager.findSceneEntityByName(entityName);
+ if (!entity || !canEntityAffectPlayerPathfinding(*entity))
+ return;
+
+ Common::Rect rect = entity->getScreenRect();
+ if (rect.isEmpty())
+ return;
+
+ Common::Rect overlap = rect;
+ overlap.clip(movementBounds);
+ if (overlap.isEmpty())
+ return;
+
+ drawClippedDebugFrame(screen, rect, color);
+}
+
+static void drawPathfindingDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
+ const SceneState &scene) {
+ if (!engine.isPathfindingDebugEnabled())
+ return;
+
+ byte displayPalette[256 * 3];
+ screen.getPalette(displayPalette);
+ const byte blue = findNearestPaletteColor(displayPalette, 0x00, 0x40, 0xff);
+ const byte green = findNearestPaletteColor(displayPalette, 0x00, 0xff, 0x00);
+ const Common::Rect movementBounds = getPathfindingMovementBounds(screen, scene.state);
+ if (movementBounds.isEmpty())
+ return;
+
+ drawClippedDebugFrame(screen, movementBounds, blue);
+
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ if (!entityManager)
+ return;
+
+ for (const ObjectRecord &object : scene.sceneObjects)
+ drawPathfindingBlockerOutline(screen, *entityManager,
+ object.objectName, movementBounds, green);
+
+ for (const AnimRecord &anim : scene.sceneAnimations)
+ drawPathfindingBlockerOutline(screen, *entityManager,
+ anim.animName, movementBounds, green);
+}
+
+static Common::String resolveTimerDebugLabel(const TimerRecord &timer, const Entity &entity) {
+ const Common::String actionTag = timer.arg2.empty() ? Common::String("<none>") : timer.arg2;
+
+ return Common::String::format("%s start=%d current=%d action=%s",
+ timer.timerName.c_str(), entity.getTimerInitialValue(),
+ entity.getTimerCurrentValue(), actionTag.c_str());
+}
+
+static void drawTimerDebugOverlay(HarvesterEngine &engine, Graphics::Screen &screen,
+ const SceneState &) {
+ if (!engine.isTimerDebugEnabled())
+ return;
+
+ const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ Script *script = engine.getScript();
+ if (!font || !entityManager || !script)
+ return;
+
+ Common::Array<Common::String> labels;
+ for (const TimerRecord &timer : script->getTimers()) {
+ const Entity *entity = entityManager->findSceneEntityByName(timer.timerName);
+ if (!entity || entity->getClassId() != kEntityClassTimer || !entity->isTimerEnabled())
+ continue;
+
+ const TimerRecord *runtimeTimer = script->findRuntimeTimerRecord(timer.timerName);
+ labels.push_back(resolveTimerDebugLabel(runtimeTimer ? *runtimeTimer : timer, *entity));
+ }
+ if (labels.empty())
+ return;
+
+ byte displayPalette[256 * 3];
+ screen.getPalette(displayPalette);
+ const byte black = findNearestPaletteColor(displayPalette, 0x00, 0x00, 0x00);
+ const byte white = findNearestPaletteColor(displayPalette, 0xff, 0xff, 0xff);
+
+ const int labelHeight = font->getFontHeight() + kRoomDebugLabelPaddingY * 2;
+ const int lineHeight = labelHeight + kTimerDebugOverlayLineSpacing;
+ const int totalHeight = (int)labels.size() * labelHeight +
+ (int)(labels.size() - 1) * kTimerDebugOverlayLineSpacing;
+ const int x = screen.w / kTimerDebugOverlayXDivisor;
+ const int y = CLIP<int>((screen.h - totalHeight) / 2, 0, MAX(0, screen.h - totalHeight));
+
+ for (uint i = 0; i < labels.size(); ++i)
+ drawRoomDebugLabel(screen, *font, labels[i], x, y + (int)i * lineHeight, white, black);
+}
+
+void RoomPresentation::drawRoomScene(HarvesterEngine &engine, Graphics::Screen &screen, const SceneState &scene,
+ float brightness) {
+ setScaledRoomPalette(screen, scene.palette, brightness);
+ screen.fillRect(screen.getBounds(), 0);
+ if (engine.getRuntimeEntities())
+ engine.getRuntimeEntities()->drawSceneEntities(screen);
+ drawRoomDebugOverlay(engine, screen, scene);
+ drawCombatDebugOverlay(engine, screen, scene);
+ drawPathfindingDebugOverlay(engine, screen, scene);
+ drawTimerDebugOverlay(engine, screen, scene);
+}
+
RoomPresentation::RoomPresentation(HarvesterEngine &engine, SceneState &scene,
const Art *art, const Graphics::Font *inspectFont, bool useNativeInspectFont)
: _engine(engine), _scene(scene), _art(art), _inspectFont(inspectFont),
diff --git a/engines/harvester/room_presentation.h b/engines/harvester/room_presentation.h
index d5f39737f9d..577da6b4fe3 100644
--- a/engines/harvester/room_presentation.h
+++ b/engines/harvester/room_presentation.h
@@ -63,6 +63,9 @@ public:
RoomPresentation(HarvesterEngine &engine, SceneState &scene,
const Art *art, const Graphics::Font *inspectFont, bool useNativeInspectFont);
+ static void drawRoomScene(HarvesterEngine &engine, Graphics::Screen &screen,
+ const SceneState &scene, float brightness);
+
bool captureDialogueBackdrop(IndexedBitmap &dialogueBackdrop);
Common::Error applyLightingCommand(StartupLightingCommand lightingCommand);
Common::Error runModalShowText(const ResolvedText &modalText, Flow &flow);
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index fc8c0d122fb..c2dd2d51c30 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -73,8 +73,6 @@ Common::Rect getRoomObjectHotspotBounds(const ObjectRecord &object);
bool shouldDisplaySceneAnimation(const AnimRecord &anim);
bool loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resources, SceneState &scene);
bool shouldRunStartupRoomProbe();
-void drawRoomScene(HarvesterEngine &engine, Graphics::Screen &screen, const SceneState &scene,
- float brightness);
const ObjectRecord *findSceneObjectByName(const Common::Array<ObjectRecord> &objects,
const Common::String &objectName);
const RegionRecord *findSceneRegionByName(const Common::Array<RegionRecord> ®ions,
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index d90da2d6beb..7aa923c77fd 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -488,7 +488,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
: hoverState.cursorSequence);
}
- drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
+ RoomPresentation::drawRoomScene(_engine, *activeScreen, _scene, _scene.targetPaletteBrightness);
_combatEffects.drawCombatDamagePopups(*activeScreen, _engine.isCombatDebugEnabled());
if (_engine.getScript() && playerState.entity) {
drawCombatLoadoutResourceIcons(*activeScreen, *_view.art, *_engine.getScript(),
@@ -1061,7 +1061,7 @@ Common::Error SceneRunner::runRoomLoop(Flow &flow, const Common::String &targetN
return transitionError;
logScenePaletteSummary("room setup initial palette", scene, 0.0f);
- drawRoomScene(_engine, *screen, scene, 0.0f);
+ RoomPresentation::drawRoomScene(_engine, *screen, scene, 0.0f);
screen->makeAllDirty();
screen->update();
Commit: 30996893141fcab19f737325026a0347725b9451
https://github.com/scummvm/scummvm/commit/30996893141fcab19f737325026a0347725b9451
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Replace Flow access bridge with explicit operations
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/dialogue.cpp
engines/harvester/flow.h
engines/harvester/harvester.cpp
engines/harvester/input.cpp
engines/harvester/menu.cpp
engines/harvester/scene.cpp
diff --git a/engines/harvester/dialogue.cpp b/engines/harvester/dialogue.cpp
index 48b0992f189..a67dc6c09ac 100644
--- a/engines/harvester/dialogue.cpp
+++ b/engines/harvester/dialogue.cpp
@@ -92,29 +92,6 @@
namespace Harvester {
-class DialogueFlowAccess {
-public:
- static bool handleSystemEvent(Flow &flow, const Common::Event &event, Common::Error &result) {
- return flow.handleSystemEvent(event, result);
- }
-
- static void executeStartupAudioCommands(Flow &flow, const Common::Array<AudioCommand> &commands) {
- flow.executeStartupAudioCommands(commands);
- }
-
- static void queueDialogueInteraction(Flow &flow, const InteractionResult &interaction) {
- flow.queueDialogueInteraction(interaction);
- }
-
- static void requestGameOverReturn(Flow &flow) {
- flow.requestGameOverReturn();
- }
-
- static const MenuTextConfig &getMenuTextConfig(const Flow &flow) {
- return flow._menuTextConfig;
- }
-};
-
namespace {
static const int kDialogueOverlayX = 167;
@@ -407,7 +384,7 @@ public:
const IndexedBitmap &backdrop, const byte *palette, float paletteBrightness,
const NpcRecord &npc)
: _engine(engine), _mousePos(mousePos), _flow(flow),
- _menuTextConfig(DialogueFlowAccess::getMenuTextConfig(flow)), _backdrop(backdrop),
+ _menuTextConfig(flow.getMenuTextConfig()), _backdrop(backdrop),
_palette(palette), _paletteBrightness(paletteBrightness), _npc(npc),
_script(engine.getScript()), _text(engine.getText()), _art(engine.getArt()),
_entityManager(engine.getRuntimeEntities()),
@@ -512,7 +489,7 @@ public:
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result)) {
+ if (_flow.handleSystemEvent(event, result)) {
_engine.stopSpeech();
return result;
}
@@ -548,7 +525,7 @@ public:
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result))
+ if (_flow.handleSystemEvent(event, result))
return result;
if (isDialogueContinueEvent(event))
@@ -638,7 +615,7 @@ public:
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result))
+ if (_flow.handleSystemEvent(event, result))
return result;
if (event.type == Common::EVENT_MOUSEMOVE)
_mousePos = event.mouse;
@@ -663,7 +640,7 @@ public:
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result))
+ if (_flow.handleSystemEvent(event, result))
return result;
switch (event.type) {
@@ -741,7 +718,7 @@ public:
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result)) {
+ if (_flow.handleSystemEvent(event, result)) {
if (editingOther && _entityManager)
_entityManager->showCursor();
return result;
@@ -847,7 +824,7 @@ public:
// GOG run_game_over_screen (0x7c540) enters run_main_menu (0x67390)
// with GAMEOVER.BM and GAMEOVER.PAL retained as the menu backdrop.
debugC(1, kDebugDialogue, "Harvester: dialogue death requesting game-over menu");
- DialogueFlowAccess::requestGameOverReturn(_flow);
+ _flow.requestGameOverReturn();
return Common::kNoError;
}
@@ -888,7 +865,7 @@ public:
interaction.lightingCommand != kStartupLightingCommandNone ||
interaction.requestPlayerGotoXZ ||
!interaction.audioCommands.empty()) {
- DialogueFlowAccess::queueDialogueInteraction(_flow, interaction);
+ _flow.queueDialogueInteraction(interaction);
}
}
@@ -896,7 +873,7 @@ public:
if (!interaction.musicPath.empty())
(void)_engine.playMusic(interaction.musicPath);
if (!interaction.audioCommands.empty())
- DialogueFlowAccess::executeStartupAudioCommands(_flow, interaction.audioCommands);
+ _flow.executeStartupAudioCommands(interaction.audioCommands);
interaction.musicPath.clear();
interaction.audioCommands.clear();
}
@@ -930,7 +907,7 @@ private:
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result))
+ if (_flow.handleSystemEvent(event, result))
return result;
}
@@ -1231,7 +1208,7 @@ private:
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
Common::Error result = Common::kNoError;
- if (DialogueFlowAccess::handleSystemEvent(_flow, event, result))
+ if (_flow.handleSystemEvent(event, result))
return result;
if (event.type == Common::EVENT_KEYDOWN) {
diff --git a/engines/harvester/flow.h b/engines/harvester/flow.h
index 804c01862ea..9fc4999adac 100644
--- a/engines/harvester/flow.h
+++ b/engines/harvester/flow.h
@@ -40,7 +40,6 @@ struct Event;
namespace Harvester {
class HarvesterEngine;
-class DialogueFlowAccess;
class Interaction;
struct IndexedBitmap;
@@ -55,11 +54,16 @@ public:
Common::Error showCdChangePrompt(int discNumber);
bool handleSystemEvent(const Common::Event &event, Common::Error &result);
+ const MenuTextConfig &getMenuTextConfig() const { return _menuTextConfig; }
+ void executeStartupAudioCommands(const Common::Array<AudioCommand> &commands);
+ void queueDialogueInteraction(const InteractionResult &interaction);
+ void requestGameOverReturn();
+
+ bool hasQueuedDebugInteraction() const { return _hasQueuedDebugInteraction; }
+ bool queueDebugInteraction(const InteractionResult &interaction);
+ bool requestDebugRoomChange(const Common::String &roomName);
+
private:
- friend class HarvesterEngine;
- friend class DialogueFlowAccess;
- friend class DialogueSystem;
- friend class InventorySystem;
friend class MenuSystem;
friend class Interaction;
friend class SceneRunner;
@@ -90,18 +94,13 @@ private:
Common::Error fadePalette(const byte *palette, float fromBrightness, float toBrightness);
bool waitForPaletteFadeTick(uint32 startTick, Common::Error &result);
bool pumpTransitionEvents(Common::Error &result);
- void executeStartupAudioCommands(const Common::Array<AudioCommand> &commands);
- void queueDialogueInteraction(const InteractionResult &interaction);
bool takeQueuedDialogueInteraction(InteractionResult &interaction);
- bool hasQueuedDebugInteraction() const { return _hasQueuedDebugInteraction; }
- bool queueDebugInteraction(const InteractionResult &interaction);
bool takeQueuedDebugInteraction(InteractionResult &interaction);
void prepareForNewGame();
void requestNewGameRestart();
bool hasPendingNewGameRestart() const;
bool takePendingNewGameRestart();
void clearPendingNewGameRestart();
- void requestGameOverReturn();
bool hasPendingGameOverReturn() const;
bool takePendingGameOverReturn();
void clearPendingGameOverReturn();
@@ -113,7 +112,6 @@ private:
bool hasPendingCloseupParentRestart() const;
bool takePendingCloseupParentRestart();
void clearPendingCloseupParentRestart();
- bool requestDebugRoomChange(const Common::String &roomName);
bool hasPendingDebugRoomChange() const { return !_pendingDebugRoomName.empty(); }
Common::String takePendingDebugRoomChange();
void resetRoomNpcDialogueState();
diff --git a/engines/harvester/harvester.cpp b/engines/harvester/harvester.cpp
index 0f2e1ed503b..6deb9bf7309 100644
--- a/engines/harvester/harvester.cpp
+++ b/engines/harvester/harvester.cpp
@@ -358,7 +358,7 @@ Common::Error HarvesterEngine::run() {
if (!flow.load())
return Common::kReadingFailed;
- if (!_media->loadQuickTipsResources(flow._menuTextConfig.hasQuickTipsHeader()))
+ if (!_media->loadQuickTipsResources(flow.getMenuTextConfig().hasQuickTipsHeader()))
return Common::kReadingFailed;
// If a savegame was selected from the launcher, load it
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index 8dfd90ec864..5cfe1c017e2 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -136,7 +136,7 @@ void Input::capturePlayerAttackTarget() {
const RoomHoverState hoverState = resolveRoomHoverState(
_engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs, _scene.sceneRegions,
- _flow._mousePos, _flow._menuTextConfig, &_flow._dialogue);
+ _flow._mousePos, _flow.getMenuTextConfig(), &_flow._dialogue);
_session.capturePlayerAttackTarget(_flow._mousePos, hoverState.npc);
}
@@ -353,7 +353,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
inventoryHover->object.objectName.c_str());
_inventory.selectItem(inventoryHover->object.objectName);
_inventory.setPromptText(_inventory.buildSelectedPrompt(
- Common::String(), _flow._menuTextConfig));
+ Common::String(), _flow.getMenuTextConfig()));
needsRedraw = true;
return InputResult();
}
@@ -384,7 +384,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
const RoomHoverState hoverState = resolveRoomHoverState(
_engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs, _scene.sceneRegions,
- _flow._mousePos, _flow._menuTextConfig, &_flow._dialogue);
+ _flow._mousePos, _flow.getMenuTextConfig(), &_flow._dialogue);
RoomHoverState clickHoverState = hoverState;
const Entity *itemTarget = nullptr;
if (_roomItems.hasSelectedItem()) {
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index 7c6c1f8e91c..f8d118abb84 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -899,7 +899,7 @@ Common::Error MenuSystem::runMainMenu(Flow &flow) {
selectedItem, item.c_str());
if (selectedItem == kMainMenuItemNewGame) {
- const MenuTextConfig &config = flow._menuTextConfig;
+ const MenuTextConfig &config = flow.getMenuTextConfig();
IndexedBitmap menuBackdrop;
if (!captureMenuBackdrop(menuBackdrop))
@@ -1151,7 +1151,7 @@ Common::Error MenuSystem::runRoomMenu(const IndexedBitmap &backdrop, const byte
selectedItem, item.c_str());
if (selectedItem == kMainMenuItemNewGame) {
- const MenuTextConfig &config = flow._menuTextConfig;
+ const MenuTextConfig &config = flow.getMenuTextConfig();
bool confirmed = false;
Common::Error confirmError = runConfirmPrompt(
@@ -1661,7 +1661,7 @@ Common::Error MenuSystem::runConfirmPrompt(const IndexedBitmap &backdrop, const
if (!promptFont.isValid() || !choiceFont.isValid())
return Common::kReadingFailed;
- const MenuTextConfig &config = flow._menuTextConfig;
+ const MenuTextConfig &config = flow.getMenuTextConfig();
const IndexedBitmap *textbox = art->getTextboxBitmap(3);
if (!textbox || !textbox->isValid())
return Common::kReadingFailed;
@@ -1731,7 +1731,7 @@ Common::Error MenuSystem::runConfirmPrompt(const IndexedBitmap &backdrop, const
Common::Error MenuSystem::runQuitGameConfirm(const IndexedBitmap &backdrop, const byte *palette,
float paletteBrightness, Flow &flow) {
- const MenuTextConfig &config = flow._menuTextConfig;
+ const MenuTextConfig &config = flow.getMenuTextConfig();
bool confirmed = false;
Common::Error confirmError = runConfirmPrompt(
@@ -1772,7 +1772,7 @@ Common::Error MenuSystem::runPasswordPrompt(const IndexedBitmap &backdrop, const
while (!_engine.shouldQuit()) {
if (needsRedraw) {
renderPasswordPromptScreen(_engine, backdrop, palette, paletteBrightness,
- titleFont, entryFont, *art, flow._menuTextConfig.enterPasswordLabel,
+ titleFont, entryFont, *art, flow.getMenuTextConfig().enterPasswordLabel,
password, cursorVisible, drawLogo);
needsRedraw = false;
}
@@ -1882,7 +1882,7 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
if (!selectedFont.isValid() || !unselectedFont.isValid())
return Common::kReadingFailed;
- const MenuTextConfig &config = flow._menuTextConfig;
+ const MenuTextConfig &config = flow.getMenuTextConfig();
IndexedBitmap volumeBar;
IndexedBitmap indicator;
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index 7aa923c77fd..df08527a01a 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -426,7 +426,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
RoomHoverState hoverState = suppressHover
? RoomHoverState()
: resolveRoomHoverState(_engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs,
- _scene.sceneRegions, _flow._mousePos, _flow._menuTextConfig, &_flow._dialogue);
+ _scene.sceneRegions, _flow._mousePos, _flow.getMenuTextConfig(), &_flow._dialogue);
Common::String promptText;
Common::String inventoryTooltipText;
auto resolveCarryTargetLabel = [&]() {
@@ -458,11 +458,11 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
targetLabel = resolveCarryTargetLabel();
}
if (inventorySelectionActive) {
- promptText = _inventory.buildSelectedPrompt(targetLabel, _flow._menuTextConfig);
+ promptText = _inventory.buildSelectedPrompt(targetLabel, _flow.getMenuTextConfig());
_inventory.setPromptText(promptText);
} else {
promptText = buildUseItemPrompt(
- _flow._menuTextConfig, _roomItems.getCarriedRoomItemLabel(), targetLabel);
+ _flow.getMenuTextConfig(), _roomItems.getCarriedRoomItemLabel(), targetLabel);
}
hoverState.cursorSequence = 7;
} else if (_inventory.isOpen()) {
@@ -497,7 +497,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
if (_inventory.isOpen()) {
_inventory.drawOverlay(*activeScreen);
drawInventoryWeekday(*activeScreen, *_view.inventoryTooltipFont,
- _inventory.resolveWeekdayLabel(_flow._menuTextConfig));
+ _inventory.resolveWeekdayLabel(_flow.getMenuTextConfig()));
}
if (inventorySelectionActive) {
_inventory.drawSelectedDragItem(*activeScreen, _flow._mousePos);
@@ -688,7 +688,7 @@ InputResult Scene::runRoomFrames(const Common::String ¤tRoomTarget) {
captureCurrentSaveState();
if (shouldRunStartupRoomProbe())
- logStartupRoomProbe(_engine, _scene, currentRoomTarget, _flow._mousePos, _flow._menuTextConfig);
+ logStartupRoomProbe(_engine, _scene, currentRoomTarget, _flow._mousePos, _flow.getMenuTextConfig());
while (!_engine.shouldQuit()) {
if (_flow.hasPendingMainMenuReturn())
Commit: 704302dcdc8b329dd4da3046d28452b8e1d460be
https://github.com/scummvm/scummvm/commit/704302dcdc8b329dd4da3046d28452b8e1d460be
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Encapsulate remaining Flow state access
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.cpp
engines/harvester/flow.h
engines/harvester/input.cpp
engines/harvester/menu.cpp
engines/harvester/room_support.h
engines/harvester/scene.cpp
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index b9de7ecbd8d..e88d6ed5eee 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -814,6 +814,11 @@ RoomHoverState resolveRoomHoverState(HarvesterEngine &engine, const RoomSetupSta
return hoverState;
}
+RoomHoverState Flow::getRoomHoverState(const SceneState &scene) const {
+ return resolveRoomHoverState(_engine, scene.state, scene.sceneObjects,
+ scene.state.roomNpcs, scene.sceneRegions, _mousePos, _menuTextConfig, &_dialogue);
+}
+
static bool findRoomObjectProbePoint(HarvesterEngine &engine, const Common::Array<ObjectRecord> &sceneObjects,
const ObjectRecord &object, Common::Point &probePoint) {
const Common::Rect bounds = getRoomObjectHotspotBounds(object);
@@ -852,11 +857,9 @@ static bool findRoomObjectProbePoint(HarvesterEngine &engine, const Common::Arra
return false;
}
-void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
- const Common::String &entranceName, Common::Point &mousePos,
- const MenuTextConfig &menuTextConfig) {
- EntityManager *entityManager = engine.getRuntimeEntities();
- Script *script = engine.getScript();
+void Flow::logStartupRoomProbe(const SceneState &scene, const Common::String &entranceName) {
+ EntityManager *entityManager = _engine.getRuntimeEntities();
+ Script *script = _engine.getScript();
if (!entityManager || !script)
return;
@@ -890,19 +893,19 @@ void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
continue;
Common::Point probePoint;
- if (!findRoomObjectProbePoint(engine, scene.sceneObjects, object, probePoint))
+ if (!findRoomObjectProbePoint(_engine, scene.sceneObjects, object, probePoint))
continue;
- const ObjectRecord *hoveredObject = findRoomObjectAtPoint(engine, scene.sceneObjects, probePoint);
+ const ObjectRecord *hoveredObject = findRoomObjectAtPoint(_engine, scene.sceneObjects, probePoint);
if (!hoveredObject)
continue;
- mousePos = probePoint;
+ _mousePos = probePoint;
const Common::String objectLabel = script->resolveObjectLabel(*hoveredObject);
ResolvedText inspectText;
const RoomHoverState hoverState = resolveRoomHoverState(
- engine, scene.state, scene.sceneObjects, scene.state.roomNpcs, scene.sceneRegions,
- probePoint, menuTextConfig);
+ _engine, scene.state, scene.sceneObjects, scene.state.roomNpcs, scene.sceneRegions,
+ probePoint, _menuTextConfig);
const bool hasInteraction = script->hasObjectInteraction(*hoveredObject);
const bool hasInspectText = script->resolveObjectInspectText(*hoveredObject, inspectText);
debugC(1, kDebugRoom,
@@ -918,8 +921,8 @@ void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
for (int y = scene.state.roomMaxZScreenY; y <= scene.state.roomMinZScreenY && !foundFloorProbe; y += 12) {
for (int x = 48; x < 592; x += 16) {
const RoomHoverState candidateHover = resolveRoomHoverState(
- engine, scene.state, scene.sceneObjects, scene.state.roomNpcs, scene.sceneRegions,
- Common::Point(x, y), menuTextConfig);
+ _engine, scene.state, scene.sceneObjects, scene.state.roomNpcs, scene.sceneRegions,
+ Common::Point(x, y), _menuTextConfig);
if (candidateHover.cursorSequence == kCursorSequenceWalk) {
floorProbe = Common::Point(x, y);
foundFloorProbe = true;
@@ -929,8 +932,8 @@ void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
}
const RoomHoverState floorHover = foundFloorProbe
- ? resolveRoomHoverState(engine, scene.state, scene.sceneObjects, scene.state.roomNpcs,
- scene.sceneRegions, floorProbe, menuTextConfig)
+ ? resolveRoomHoverState(_engine, scene.state, scene.sceneObjects, scene.state.roomNpcs,
+ scene.sceneRegions, floorProbe, _menuTextConfig)
: RoomHoverState();
debugC(1, kDebugRoom,
"Harvester: startup probe floor room='%s' point=(%d,%d) found=%d cursor_sequence=%d prompt='%s'",
@@ -943,7 +946,7 @@ void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
probePlayer.initialize(scene.state, player, 0);
probePlayer.setMoveTargetFromScreenPoint(scene.state, floorProbe.x, floorProbe.y);
for (int i = 0; i < 32 && probePlayer.getState().hasMoveTarget; ++i)
- (void)probePlayer.stepMoveTarget(engine, scene.state, scene.sceneObjects, scene.sceneAnimations);
+ (void)probePlayer.stepMoveTarget(_engine, scene.state, scene.sceneObjects, scene.sceneAnimations);
const Common::Rect movedRect = player->getScreenRect();
debugC(1, kDebugPlayer,
diff --git a/engines/harvester/flow.h b/engines/harvester/flow.h
index 9fc4999adac..35e34459728 100644
--- a/engines/harvester/flow.h
+++ b/engines/harvester/flow.h
@@ -55,6 +55,14 @@ public:
bool handleSystemEvent(const Common::Event &event, Common::Error &result);
const MenuTextConfig &getMenuTextConfig() const { return _menuTextConfig; }
+ const Common::Point &getMousePos() const { return _mousePos; }
+ uint getQuickTipCount() const { return _quickTips.size(); }
+ const Common::String &getQuickTip(uint index) const { return _quickTips[index]; }
+ bool hasRoomNpcHandler(const Common::String &npcName) const { return _dialogue.hasRoomNpcHandler(npcName); }
+ bool isNestedRoomLoop() const { return _roomLoopDepth > 1; }
+ RoomHoverState getRoomHoverState(const SceneState &scene) const;
+ void logStartupRoomProbe(const SceneState &scene, const Common::String &entranceName);
+
void executeStartupAudioCommands(const Common::Array<AudioCommand> &commands);
void queueDialogueInteraction(const InteractionResult &interaction);
void requestGameOverReturn();
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index 5cfe1c017e2..6029618b424 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -134,18 +134,16 @@ void Input::capturePlayerAttackTarget() {
player.clearAttackTarget();
- const RoomHoverState hoverState = resolveRoomHoverState(
- _engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs, _scene.sceneRegions,
- _flow._mousePos, _flow.getMenuTextConfig(), &_flow._dialogue);
- _session.capturePlayerAttackTarget(_flow._mousePos, hoverState.npc);
+ const RoomHoverState hoverState = _flow.getRoomHoverState(_scene);
+ _session.capturePlayerAttackTarget(_flow.getMousePos(), hoverState.npc);
}
void Input::handleMouseMove(bool &needsRedraw) {
if (_inventory.isOpen() && _inventory.hasSelection()) {
- const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow._mousePos);
+ const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow.getMousePos());
// Native inventory handoff is driven by the latched selected item, not by
// a second click after the selection has already been made.
- if (!inventoryHover && isOutsideNativeInventoryDragCloseBounds(_flow._mousePos)) {
+ if (!inventoryHover && isOutsideNativeInventoryDragCloseBounds(_flow.getMousePos())) {
if (_inventory.close())
needsRedraw = true;
}
@@ -168,8 +166,8 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
return InputResult();
_session.clearPendingRegionInteraction();
if (_inventory.isOpen()) {
- const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow._mousePos);
- debugLogInventoryClick("right", _flow._mousePos, inventoryHover);
+ const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow.getMousePos());
+ debugLogInventoryClick("right", _flow.getMousePos(), inventoryHover);
if (_inventory.hasSelection()) {
debugC(1, kDebugInventory,
"Harvester: inventory right click cleared active selection='%s'",
@@ -277,7 +275,7 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
player.cancelMovementForAttack();
(void)player.syncCombatLoadoutVisual(_engine, _scene.state, script->getPlayerCombatLoadout());
capturePlayerAttackTarget();
- if (player.startAttackAnimation(_scene.state, _flow._mousePos)) {
+ if (player.startAttackAnimation(_scene.state, _flow.getMousePos())) {
debugC(1, kDebugCombat,
"Harvester: combat player attack start loadout=%d weapon='%s' damage=%d damage_type='%s' target_class='%s' target='%s' cursor=(%d,%d)",
playerState.combatLoadout,
@@ -285,7 +283,7 @@ InputResult Input::handleRightButtonDown(bool &needsRedraw) {
Player::resolveCombatLoadoutDamageAmount(playerState.combatLoadout),
Player::describeCombatDamageType(Player::resolveCombatLoadoutDamageType(playerState.combatLoadout)),
describeCombatTargetClass(playerState.attackTargetClassId),
- playerState.attackTargetName.c_str(), _flow._mousePos.x, _flow._mousePos.y);
+ playerState.attackTargetName.c_str(), _flow.getMousePos().x, _flow.getMousePos().y);
needsRedraw = true;
} else {
player.clearAttackTarget();
@@ -333,8 +331,8 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
const Common::Rect inventoryPanelBounds = _inventory.getPanelBounds();
if (_inventory.isOpen()) {
- const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow._mousePos);
- debugLogInventoryClick("left", _flow._mousePos, inventoryHover);
+ const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow.getMousePos());
+ debugLogInventoryClick("left", _flow.getMousePos(), inventoryHover);
if (inventoryHover) {
if (InventorySystem::isExitObject(inventoryHover->object)) {
debugC(1, kDebugInventory, "Harvester: inventory left click exit button");
@@ -373,29 +371,27 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
}
if (_inventory.hasSelection()) {
- if (!inventoryPanelBounds.contains(_flow._mousePos) && _inventory.close())
+ if (!inventoryPanelBounds.contains(_flow.getMousePos()) && _inventory.close())
needsRedraw = true;
return InputResult();
}
- if (!inventoryPanelBounds.contains(_flow._mousePos) && _inventory.close())
+ if (!inventoryPanelBounds.contains(_flow.getMousePos()) && _inventory.close())
needsRedraw = true;
return InputResult();
}
- const RoomHoverState hoverState = resolveRoomHoverState(
- _engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs, _scene.sceneRegions,
- _flow._mousePos, _flow.getMenuTextConfig(), &_flow._dialogue);
+ const RoomHoverState hoverState = _flow.getRoomHoverState(_scene);
RoomHoverState clickHoverState = hoverState;
const Entity *itemTarget = nullptr;
if (_roomItems.hasSelectedItem()) {
clickHoverState = RoomHoverState();
- itemTarget = _roomItems.findSelectedItemTarget(_flow._mousePos);
+ itemTarget = _roomItems.findSelectedItemTarget(_flow.getMousePos());
if (!itemTarget)
return InputResult();
if (itemTarget == playerState.entity)
clickHoverState.playerEntity = itemTarget;
if (itemTarget->getClassId() == kEntityClassNpc &&
- _flow._dialogue.hasRoomNpcHandler(itemTarget->getName()) &&
+ _flow.hasRoomNpcHandler(itemTarget->getName()) &&
_engine.getScript()->isNamedNpcDeathTypeClear(itemTarget->getName())) {
for (const NpcRecord &npc : _scene.state.roomNpcs) {
if (npc.npcName.equalsIgnoreCase(itemTarget->getName())) {
@@ -408,7 +404,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
}
debugC(1, kDebugRoom,
"Harvester: room click room='%s' mouse=(%d,%d) object='%s' npc='%s' region='%s' cursor_sequence=%d prompt='%s'",
- _scene.state.roomName.c_str(), _flow._mousePos.x, _flow._mousePos.y,
+ _scene.state.roomName.c_str(), _flow.getMousePos().x, _flow.getMousePos().y,
clickHoverState.object ? clickHoverState.object->objectName.c_str() : "",
clickHoverState.npc ? clickHoverState.npc->npcName.c_str() : "",
clickHoverState.region ? clickHoverState.region->regionName.c_str() : "",
@@ -497,7 +493,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
needsRedraw = true;
return InputResult();
}
- _interactionProcessor.queueRegionInteraction(*hoverState.region, _flow._mousePos);
+ _interactionProcessor.queueRegionInteraction(*hoverState.region, _flow.getMousePos());
Common::Error interactionError =
_interactionProcessor.tryActivatePendingRegion(_inventory, needsRedraw);
if (interactionError.getCode() != Common::kNoError)
@@ -515,17 +511,17 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
const Common::Rect playerRect = playerState.entity->getScreenRect();
debugC(1, kDebugPathfinding,
"Harvester: pathfinding click accepted room='%s' mouse=(%d,%d) movement_band=(y=%d..%d,z=%d..%d) player=(%d,%d,z=%.2f) player_rect=(%d,%d)-(%d,%d)",
- _scene.state.roomName.c_str(), _flow._mousePos.x, _flow._mousePos.y,
+ _scene.state.roomName.c_str(), _flow.getMousePos().x, _flow.getMousePos().y,
_scene.state.roomMaxZScreenY, _scene.state.roomMinZScreenY,
_scene.state.roomMinZ, _scene.state.roomMaxZ,
playerState.centerX, playerState.bottomY, (double)playerState.z,
playerRect.left, playerRect.top, playerRect.right, playerRect.bottom);
}
- player.setMoveTargetFromScreenPoint(_scene.state, _flow._mousePos.x, _flow._mousePos.y);
+ player.setMoveTargetFromScreenPoint(_scene.state, _flow.getMousePos().x, _flow.getMousePos().y);
if (_engine.isPathfindingDebugEnabled()) {
debugC(1, kDebugPathfinding,
"Harvester: pathfinding click target room='%s' mouse=(%d,%d) target=(%d,%d,z=%.2f)",
- _scene.state.roomName.c_str(), _flow._mousePos.x, _flow._mousePos.y,
+ _scene.state.roomName.c_str(), _flow.getMousePos().x, _flow.getMousePos().y,
playerState.targetX, playerState.targetBottomY, (double)playerState.targetZ);
}
needsRedraw = true;
@@ -688,7 +684,7 @@ InputResult Input::handleKeyDown(const Common::KeyState &key, bool &needsRedraw)
key.keycode == Common::KEYCODE_RCTRL) {
inputState.attackModifierHeld = true;
} else if (key.keycode == Common::KEYCODE_k && _engine.isCombatDebugEnabled()) {
- Common::Error debugKillError = _session.killDebugActiveMonster(_flow._mousePos, needsRedraw);
+ Common::Error debugKillError = _session.killDebugActiveMonster(_flow.getMousePos(), needsRedraw);
if (debugKillError.getCode() != Common::kNoError)
return InputResult::leaveRoom(debugKillError);
return InputResult();
diff --git a/engines/harvester/menu.cpp b/engines/harvester/menu.cpp
index f8d118abb84..e2653e448c2 100644
--- a/engines/harvester/menu.cpp
+++ b/engines/harvester/menu.cpp
@@ -1896,7 +1896,7 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
int capturedSlider = -1;
bool showingQuickTips = false;
bool needsRedraw = true;
- uint quickTipIndex = flow._quickTips.empty() ? 0 : _engine.getRandomNumber(flow._quickTips.size() - 1);
+ uint quickTipIndex = flow.getQuickTipCount() == 0 ? 0 : _engine.getRandomNumber(flow.getQuickTipCount() - 1);
QuickTipsLayout quickTipsLayout;
auto persistConfig = [&]() -> bool {
@@ -2009,7 +2009,7 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
toggleGore();
break;
case 5:
- if (!flow._quickTips.empty()) {
+ if (flow.getQuickTipCount() != 0) {
if (!resolveQuickTipsLayout(_engine, config, quickTipsLayout))
return Common::kReadingFailed;
showingQuickTips = true;
@@ -2031,7 +2031,7 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
if (needsRedraw) {
if (showingQuickTips) {
renderQuickTipsOverlay(_engine, backdrop, palette, paletteBrightness,
- config, quickTipsLayout, flow._quickTips[quickTipIndex]);
+ config, quickTipsLayout, flow.getQuickTip(quickTipIndex));
} else {
renderOptionsMenuScreen(_engine, backdrop, palette, paletteBrightness,
selectedFont, unselectedFont, *art, config, volumeBar, indicator, selectedItem);
@@ -2055,7 +2055,7 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
showingQuickTips = false;
needsRedraw = true;
} else if (quickTipsLayout.nextRect.contains(_mousePos)) {
- quickTipIndex = (quickTipIndex + 1) % flow._quickTips.size();
+ quickTipIndex = (quickTipIndex + 1) % flow.getQuickTipCount();
needsRedraw = true;
} else if (quickTipsLayout.toggleRect.contains(_mousePos)) {
script->setQuickTipsEnabled(!script->isQuickTipsEnabled());
@@ -2174,7 +2174,7 @@ Common::Error MenuSystem::runOptionsMenu(const IndexedBitmap &backdrop, const by
break;
case Common::KEYCODE_q:
selectedItem = 5;
- if (!flow._quickTips.empty()) {
+ if (flow.getQuickTipCount() != 0) {
showingQuickTips = true;
needsRedraw = true;
}
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index c2dd2d51c30..b8b110a4a0a 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -92,9 +92,6 @@ RoomHoverState resolveRoomHoverState(HarvesterEngine &engine, const RoomSetupSta
const Common::Array<RegionRecord> ®ions,
const Common::Point &mousePos, const MenuTextConfig &menuTextConfig,
const DialogueSystem *dialogue = nullptr);
-void logStartupRoomProbe(HarvesterEngine &engine, const SceneState &scene,
- const Common::String &entranceName, Common::Point &mousePos,
- const MenuTextConfig &menuTextConfig);
} // End of namespace Harvester
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index df08527a01a..9d59fd9fde7 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -419,18 +419,17 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
const bool inventorySelectionActive = _inventory.hasSelection();
const bool roomCarryActive = _roomItems.hasCarriedRoomItem();
const bool activeCarry = inventorySelectionActive || roomCarryActive;
- const bool inventoryPanelContainsMouse = _inventory.isOpen() && inventoryPanelBounds.contains(_flow._mousePos);
+ const bool inventoryPanelContainsMouse = _inventory.isOpen() && inventoryPanelBounds.contains(_flow.getMousePos());
const bool suppressHover = _presentationState.showingInspectText || idleState.active || idleState.exiting ||
isPlayerCombatLocked() ||
(_inventory.isOpen() && (inventoryPanelContainsMouse || !inventorySelectionActive));
RoomHoverState hoverState = suppressHover
? RoomHoverState()
- : resolveRoomHoverState(_engine, _scene.state, _scene.sceneObjects, _scene.state.roomNpcs,
- _scene.sceneRegions, _flow._mousePos, _flow.getMenuTextConfig(), &_flow._dialogue);
+ : _flow.getRoomHoverState(_scene);
Common::String promptText;
Common::String inventoryTooltipText;
auto resolveCarryTargetLabel = [&]() {
- const Entity *target = suppressHover ? nullptr : _roomItems.findSelectedItemTarget(_flow._mousePos, false);
+ const Entity *target = suppressHover ? nullptr : _roomItems.findSelectedItemTarget(_flow.getMousePos(), false);
if (!target)
return Common::String();
if (target == playerState.entity)
@@ -445,7 +444,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
};
if (activeCarry) {
Common::String targetLabel;
- const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow._mousePos);
+ const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow.getMousePos());
if (_inventory.isOpen()) {
if (inventoryHover && !InventorySystem::isExitObject(inventoryHover->object) &&
!InventorySystem::isStatusObject(inventoryHover->object) &&
@@ -466,7 +465,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
}
hoverState.cursorSequence = 7;
} else if (_inventory.isOpen()) {
- const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow._mousePos);
+ const InventoryVisual *inventoryHover = _inventory.findItemAtPoint(_flow.getMousePos());
if (inventoryHover &&
!InventorySystem::isExitObject(inventoryHover->object)) {
inventoryTooltipText =
@@ -500,10 +499,10 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
_inventory.resolveWeekdayLabel(_flow.getMenuTextConfig()));
}
if (inventorySelectionActive) {
- _inventory.drawSelectedDragItem(*activeScreen, _flow._mousePos);
+ _inventory.drawSelectedDragItem(*activeScreen, _flow.getMousePos());
} else if (roomCarryActive && _roomItems.getCarriedRoomItemBitmap().isValid()) {
- const int drawX = _flow._mousePos.x - (int)_roomItems.getCarriedRoomItemBitmap().width / 2;
- const int drawY = _flow._mousePos.y - (int)_roomItems.getCarriedRoomItemBitmap().height / 2;
+ const int drawX = _flow.getMousePos().x - (int)_roomItems.getCarriedRoomItemBitmap().width / 2;
+ const int drawY = _flow.getMousePos().y - (int)_roomItems.getCarriedRoomItemBitmap().height / 2;
blitTransparentBitmap(*activeScreen, _roomItems.getCarriedRoomItemBitmap(), drawX, drawY);
}
@@ -688,7 +687,7 @@ InputResult Scene::runRoomFrames(const Common::String ¤tRoomTarget) {
captureCurrentSaveState();
if (shouldRunStartupRoomProbe())
- logStartupRoomProbe(_engine, _scene, currentRoomTarget, _flow._mousePos, _flow.getMenuTextConfig());
+ _flow.logStartupRoomProbe(_scene, currentRoomTarget);
while (!_engine.shouldQuit()) {
if (_flow.hasPendingMainMenuReturn())
@@ -1029,7 +1028,7 @@ Common::Error SceneRunner::runRoomLoop(Flow &flow, const Common::String &targetN
const RoomViewResources view = { art, promptFont, inspectFont, inventoryTooltipFont,
useNativePromptFont, useNativeInspectFont };
Scene session(_engine, flow, scene, entityManager, _inventory, _cheats, view,
- flow._roomLoopDepth > 1);
+ flow.isNestedRoomLoop());
debugC(1, kDebugRoom, "Harvester: created room session room='%s'", scene.state.roomName.c_str());
session.initializePlayerState();
Commit: 102331f518468d242cf9bd562ebfbff645f6cc7c
https://github.com/scummvm/scummvm/commit/102331f518468d242cf9bd562ebfbff645f6cc7c
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Remove remaining Flow friendships
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.h
diff --git a/engines/harvester/flow.h b/engines/harvester/flow.h
index 35e34459728..ca464b9535c 100644
--- a/engines/harvester/flow.h
+++ b/engines/harvester/flow.h
@@ -40,7 +40,6 @@ struct Event;
namespace Harvester {
class HarvesterEngine;
-class Interaction;
struct IndexedBitmap;
class Flow {
@@ -71,60 +70,58 @@ public:
bool queueDebugInteraction(const InteractionResult &interaction);
bool requestDebugRoomChange(const Common::String &roomName);
-private:
- friend class MenuSystem;
- friend class Interaction;
- friend class SceneRunner;
- friend class Input;
- friend class Scene;
-
- bool loadQuickTips();
- bool loadMenuItems();
- Common::Error runQuickTips();
- Common::Error runDemoIntroduction();
Common::Error runDemoEnding();
- Common::Error runMainMenu();
Common::Error runRoomMenu(const IndexedBitmap &backdrop, const byte *palette,
float paletteBrightness, bool canSaveGame);
Common::Error runRoomNpcDialogue(const IndexedBitmap &backdrop, const byte *palette,
float paletteBrightness, const ScriptExecutionContext &executionContext,
const NpcRecord &npc, const Common::String &usedItemName);
- Common::Error runTownMapSelector(const Common::String &mapEntryName, Common::String &destinationEntranceName);
Common::Error runRoomLoop(const Common::String &entranceName);
Common::Error resolveRoomTransitionTarget(const Common::String &targetName, Common::String &resolvedTargetName);
- bool ensureCursorEntity();
+
bool populateRoomSceneEntities(RoomSetupState &state,
const Common::Array<ObjectRecord> &drawableObjects,
const Common::Array<AnimRecord> &drawableAnimations);
Common::Error beginRoomSetupTransition();
Common::Error waitForRoomSetupTransitionHold();
Common::Error fadeInRoomScene(const byte *palette, float targetBrightness);
- Common::Error fadePalette(const byte *palette, float fromBrightness, float toBrightness);
- bool waitForPaletteFadeTick(uint32 startTick, Common::Error &result);
- bool pumpTransitionEvents(Common::Error &result);
+ void resetCursorAnimationSequence();
+ bool tickRuntimeEntities();
+
bool takeQueuedDialogueInteraction(InteractionResult &interaction);
bool takeQueuedDebugInteraction(InteractionResult &interaction);
+
void prepareForNewGame();
void requestNewGameRestart();
- bool hasPendingNewGameRestart() const;
bool takePendingNewGameRestart();
- void clearPendingNewGameRestart();
- bool hasPendingGameOverReturn() const;
bool takePendingGameOverReturn();
- void clearPendingGameOverReturn();
void requestMainMenuReturn();
bool hasPendingMainMenuReturn() const;
bool takePendingMainMenuReturn();
- void clearPendingMainMenuReturn();
void requestCloseupParentRestart();
- bool hasPendingCloseupParentRestart() const;
bool takePendingCloseupParentRestart();
- void clearPendingCloseupParentRestart();
bool hasPendingDebugRoomChange() const { return !_pendingDebugRoomName.empty(); }
- Common::String takePendingDebugRoomChange();
void resetRoomNpcDialogueState();
- void resetCursorAnimationSequence();
- bool tickRuntimeEntities();
+
+private:
+ bool loadQuickTips();
+ bool loadMenuItems();
+ Common::Error runQuickTips();
+ Common::Error runDemoIntroduction();
+ Common::Error runMainMenu();
+ Common::Error runTownMapSelector(const Common::String &mapEntryName, Common::String &destinationEntranceName);
+ bool ensureCursorEntity();
+ Common::Error fadePalette(const byte *palette, float fromBrightness, float toBrightness);
+ bool waitForPaletteFadeTick(uint32 startTick, Common::Error &result);
+ bool pumpTransitionEvents(Common::Error &result);
+ bool hasPendingNewGameRestart() const;
+ void clearPendingNewGameRestart();
+ bool hasPendingGameOverReturn() const;
+ void clearPendingGameOverReturn();
+ void clearPendingMainMenuReturn();
+ bool hasPendingCloseupParentRestart() const;
+ void clearPendingCloseupParentRestart();
+ Common::String takePendingDebugRoomChange();
HarvesterEngine &_engine;
Common::Array<Common::String> _quickTips;
Commit: bad29b7c895a2ad71eb127b42ce42a3d0daf41a5
https://github.com/scummvm/scummvm/commit/bad29b7c895a2ad71eb127b42ce42a3d0daf41a5
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Share room object entity construction
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/scene_entities.cpp
engines/harvester/scene_entities.h
diff --git a/engines/harvester/scene_entities.cpp b/engines/harvester/scene_entities.cpp
index fba500d6c03..205a1b26472 100644
--- a/engines/harvester/scene_entities.cpp
+++ b/engines/harvester/scene_entities.cpp
@@ -30,41 +30,6 @@ namespace Harvester {
static const char *const kInventoryOwnerName = "INVENTORY";
-static bool isBackgroundSceneObject(const RoomSetupState &state,
- const ObjectRecord &object, const Entity &entity) {
- if (!state.backgroundObjectName.empty() &&
- object.objectName.equalsIgnoreCase(state.backgroundObjectName)) {
- return true;
- }
-
- return object.initialX == 0 && object.initialY == 0 &&
- entity.getBoundsWidth() == 640 && entity.getBoundsHeight() == 480;
-}
-
-static bool isInteractiveSceneHotspot(const ObjectRecord &object, Script *script) {
- if (object.operatable || !object.actionTag.empty())
- return true;
- if (!script)
- return false;
- if (script->isPickupObject(object))
- return true;
-
- ResolvedText inspectText;
- return script->resolveObjectInspectText(object, inspectText);
-}
-
-static int resolveSceneObjectClass(const RoomSetupState &state,
- const ObjectRecord &object, const Entity *entity, Script *script) {
- if (entity)
- return isBackgroundSceneObject(state, object, *entity)
- ? kEntityClassBackground
- : kEntityClassObject;
-
- return isInteractiveSceneHotspot(object, script)
- ? kEntityClassRectHotspot
- : kEntityClassDisabledHotspot;
-}
-
static bool sameRect(const Common::Rect &lhs, const Common::Rect &rhs) {
return lhs.left == rhs.left && lhs.top == rhs.top &&
lhs.right == rhs.right && lhs.bottom == rhs.bottom;
@@ -540,12 +505,8 @@ EntityClass SceneEntities::resolveSceneObjectClassLocal(const ObjectRecord &obje
: kEntityClassDisabledHotspot;
}
-void SceneEntities::spawnSceneObjectEntityFromRecord(const ObjectRecord &object) {
- if (!_entityManager)
- return;
-
- const Common::String spritePath = resolveSceneObjectSpritePathLocal(object);
- const Common::Rect hotspotBounds = getSceneObjectBounds(object);
+Entity *SceneEntities::createSceneObjectEntity(const ObjectRecord &object,
+ const Common::String &spritePath, const Common::Rect &hotspotBounds) {
Entity *entity = nullptr;
if (!spritePath.empty() && spritePath.hasSuffixIgnoreCase(".BM")) {
entity = _entityManager->spawnSceneBitmapEntity(object.objectName, spritePath,
@@ -555,12 +516,25 @@ void SceneEntities::spawnSceneObjectEntityFromRecord(const ObjectRecord &object)
(float)object.currentZ);
}
if (!entity)
- return;
+ return nullptr;
entity->setClassId(resolveSceneObjectClassLocal(
object, entity->hasFrames() ? entity : nullptr));
entity->setAnchorMode(kEntityAnchorTopLeft);
entity->setZExtent((float)object.zExtent);
+ return entity;
+}
+
+void SceneEntities::spawnSceneObjectEntityFromRecord(const ObjectRecord &object) {
+ if (!_entityManager)
+ return;
+
+ const Common::String spritePath = resolveSceneObjectSpritePathLocal(object);
+ const Common::Rect hotspotBounds = getSceneObjectBounds(object);
+ Entity *entity = createSceneObjectEntity(object, spritePath, hotspotBounds);
+ if (!entity)
+ return;
+
debugC(3, kDebugRoom, "Harvester: scene object spawned object='%s' sprite='%s' class=0x%x",
object.objectName.c_str(), spritePath.c_str(), entity->getClassId());
}
@@ -727,16 +701,9 @@ void SceneEntities::populateRoomObjects(const Common::Array<ObjectRecord> &drawa
return;
for (const ObjectRecord &object : drawableObjects) {
- Entity *entity = nullptr;
const Common::String spritePath = resolveSceneObjectSpritePathLocal(object);
const Common::Rect hotspotBounds = getRoomObjectHotspotBounds(object);
- if (!spritePath.empty() && spritePath.hasSuffixIgnoreCase(".BM")) {
- entity = _entityManager->spawnSceneBitmapEntity(object.objectName, spritePath,
- Common::Point(object.currentX, object.currentY), (float)object.currentZ);
- } else {
- if (!hotspotBounds.isEmpty())
- entity = _entityManager->spawnSceneHotspotEntity(object.objectName, hotspotBounds, (float)object.currentZ);
- }
+ Entity *entity = createSceneObjectEntity(object, spritePath, hotspotBounds);
if (!entity) {
debugC(1, kDebugRoom,
@@ -751,10 +718,6 @@ void SceneEntities::populateRoomObjects(const Common::Array<ObjectRecord> &drawa
continue;
}
- entity->setClassId(resolveSceneObjectClass(
- _state, object, entity->hasFrames() ? entity : nullptr, _script));
- entity->setAnchorMode(kEntityAnchorTopLeft);
- entity->setZExtent((float)object.zExtent);
const Common::Rect entityRect = entity->getScreenRect();
debugC(1, kDebugRoom,
"Harvester: scene entity spawned room='%s' object='%s' type='%s' class=0x%x pos=(%d,%d,z=%.2f) rect=(%d,%d)-(%d,%d) sprite='%s' action='%s' operatable=%d ident='%s'",
diff --git a/engines/harvester/scene_entities.h b/engines/harvester/scene_entities.h
index 7265a47da3a..77cc298c1f9 100644
--- a/engines/harvester/scene_entities.h
+++ b/engines/harvester/scene_entities.h
@@ -56,6 +56,8 @@ public:
private:
bool isTimerMaterializedInCurrentRoom(const Common::String &timerName) const;
+ Entity *createSceneObjectEntity(const ObjectRecord &object,
+ const Common::String &spritePath, const Common::Rect &hotspotBounds);
bool isInteractiveSceneHotspot(const ObjectRecord &object) const;
EntityClass resolveSceneObjectClassLocal(const ObjectRecord &object, const Entity *entity) const;
static Common::Rect getSceneRegionBounds(const RegionRecord ®ion);
Commit: 41fbd50e02082cc8fd1aca6c977b8dabbb5d066c
https://github.com/scummvm/scummvm/commit/41fbd50e02082cc8fd1aca6c977b8dabbb5d066c
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Share NPC animation configuration
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/scene_entities.cpp
engines/harvester/scene_entities.h
diff --git a/engines/harvester/scene_entities.cpp b/engines/harvester/scene_entities.cpp
index 205a1b26472..c6c5490c5f7 100644
--- a/engines/harvester/scene_entities.cpp
+++ b/engines/harvester/scene_entities.cpp
@@ -593,6 +593,19 @@ bool SceneEntities::applyRoomNpcPlacement(Entity &entity, const NpcRecord &npc)
return true;
}
+void SceneEntities::configureRoomNpcAnimation(Entity &entity, const NpcRecord &npc, bool preservedCorpse) {
+ if (preservedCorpse) {
+ const int corpseFrame = MIN(entity.getLastFrame(), npc.runtimeState);
+ entity.setAnimationFrameRange(corpseFrame, corpseFrame, false);
+ entity.setAnimationRate(0);
+ entity.setCurrentFrame(corpseFrame);
+ entity.setAnimationEnabled(false);
+ } else {
+ // Native spawn_npc_entity_from_record seeds the passive room-NPC loop as frames 0..0x3b.
+ entity.setAnimationFrameRange(0, MIN(entity.getLastFrame(), kRoomNpcAmbientLastFrame), true);
+ }
+}
+
Entity *SceneEntities::spawnSceneNpcEntityFromRecord(const NpcRecord &npc) {
const bool shouldSpawnNpc = shouldSpawnRoomNpcEntity(npc);
const bool preservedCorpse = !npc.active &&
@@ -615,16 +628,9 @@ Entity *SceneEntities::spawnSceneNpcEntityFromRecord(const NpcRecord &npc) {
removeSceneEntityByName(npc.npcName);
return nullptr;
}
- if (preservedCorpse) {
- const int corpseFrame = MIN(entity->getLastFrame(), npc.runtimeState);
- entity->setAnimationFrameRange(corpseFrame, corpseFrame, false);
- entity->setAnimationRate(0);
- entity->setCurrentFrame(corpseFrame);
- entity->setAnimationEnabled(false);
- } else {
- entity->setAnimationFrameRange(0, MIN(entity->getLastFrame(), kRoomNpcAmbientLastFrame), true);
+ configureRoomNpcAnimation(*entity, npc, preservedCorpse);
+ if (!preservedCorpse)
entity->setAnimationRate(npc.frameDelay > 0 ? npc.frameDelay : 0);
- }
_entityManager->reinsertSceneEntity(entity);
return entity;
}
@@ -754,18 +760,9 @@ void SceneEntities::populateRoomNpcs() {
debug(1, "Harvester: unable to apply room npc placement for '%s'",
npc.npcName.c_str());
}
- if (isCorpse) {
- const int corpseFrame = MIN(entity->getLastFrame(), npc.runtimeState);
- entity->setAnimationFrameRange(corpseFrame, corpseFrame, false);
- entity->setAnimationRate(0);
- entity->setCurrentFrame(corpseFrame);
- entity->setAnimationEnabled(false);
- } else {
- // Native spawn_npc_entity_from_record seeds the passive room-NPC loop as frames 0..0x3b.
- entity->setAnimationFrameRange(0, MIN(entity->getLastFrame(), kRoomNpcAmbientLastFrame), true);
- if (npc.frameDelay > 0)
- entity->setAnimationRate(npc.frameDelay);
- }
+ configureRoomNpcAnimation(*entity, npc, isCorpse);
+ if (!isCorpse && npc.frameDelay > 0)
+ entity->setAnimationRate(npc.frameDelay);
_entityManager->reinsertSceneEntity(entity);
debugC(1, kDebugRoom,
"Harvester: scene npc spawned room='%s' npc='%s' class=0x%x pos=(%d,%d,z=%.2f) frame_delay=%d model='%s' active=%d visible=%d",
diff --git a/engines/harvester/scene_entities.h b/engines/harvester/scene_entities.h
index 77cc298c1f9..ee026d1eb37 100644
--- a/engines/harvester/scene_entities.h
+++ b/engines/harvester/scene_entities.h
@@ -62,6 +62,7 @@ private:
EntityClass resolveSceneObjectClassLocal(const ObjectRecord &object, const Entity *entity) const;
static Common::Rect getSceneRegionBounds(const RegionRecord ®ion);
static bool applyRoomNpcPlacement(Entity &entity, const NpcRecord &npc);
+ static void configureRoomNpcAnimation(Entity &entity, const NpcRecord &npc, bool preservedCorpse);
RoomSetupState &_state;
Script *_script;
Commit: 0c2252ad1520011e2dd3ddc55b1262f8552fce0b
https://github.com/scummvm/scummvm/commit/0c2252ad1520011e2dd3ddc55b1262f8552fce0b
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Share monster entity construction
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/scene_entities.cpp
engines/harvester/scene_entities.h
diff --git a/engines/harvester/scene_entities.cpp b/engines/harvester/scene_entities.cpp
index c6c5490c5f7..ea36d0bc160 100644
--- a/engines/harvester/scene_entities.cpp
+++ b/engines/harvester/scene_entities.cpp
@@ -635,10 +635,7 @@ Entity *SceneEntities::spawnSceneNpcEntityFromRecord(const NpcRecord &npc) {
return entity;
}
-Entity *SceneEntities::spawnSceneMonsterEntityFromRecord(const RoomSetupState &roomState, const MonsterRecord &monster) {
- if (!_entityManager || !shouldSpawnRoomMonsterEntity(monster))
- return nullptr;
-
+Entity *SceneEntities::createSceneMonsterEntity(const MonsterRecord &monster) {
Entity *entity = _entityManager->spawnSceneActorEntity(
monster.monsterName, monster.modelPath,
Common::Point(monster.posX, monster.posY), (float)monster.posZ,
@@ -651,6 +648,17 @@ Entity *SceneEntities::spawnSceneMonsterEntityFromRecord(const RoomSetupState &r
entity->setHitTestMode(kEntityHitTestNone);
entity->setVisible(monster.visible);
Monster::applyAnimation(*entity, monster);
+ return entity;
+}
+
+Entity *SceneEntities::spawnSceneMonsterEntityFromRecord(const RoomSetupState &roomState, const MonsterRecord &monster) {
+ if (!_entityManager || !shouldSpawnRoomMonsterEntity(monster))
+ return nullptr;
+
+ Entity *entity = createSceneMonsterEntity(monster);
+ if (!entity)
+ return nullptr;
+
if (!applyRoomActorPlacement(roomState, *entity, monster.posX, monster.posY, (float)monster.posZ)) {
removeSceneEntityByName(monster.monsterName);
return nullptr;
@@ -777,21 +785,13 @@ void SceneEntities::populateRoomMonsters() {
return;
for (const MonsterRecord &monster : _state.roomMonsters) {
- Entity *entity = _entityManager->spawnSceneActorEntity(monster.monsterName,
- monster.modelPath, Common::Point(monster.posX, monster.posY), (float)monster.posZ,
- Monster::resolveFacingFrame(monster.facing));
+ Entity *entity = createSceneMonsterEntity(monster);
if (!entity) {
debug(1, "Harvester: unable to spawn room monster entity '%s' from '%s'",
monster.monsterName.c_str(), monster.modelPath.c_str());
continue;
}
- entity->setClassId(kEntityClassMonster);
- entity->setZExtent(kNativeNpcMonsterZExtent);
- entity->setHitTestMode(kEntityHitTestNone);
- entity->setVisible(monster.visible);
- // Native restores a saved monster corpse frame before set_entity_screen_position().
- Monster::applyAnimation(*entity, monster);
if (!applyRoomActorPlacement(_state, *entity, monster.posX, monster.posY, (float)monster.posZ)) {
debug(1, "Harvester: unable to apply room monster placement for '%s'",
monster.monsterName.c_str());
diff --git a/engines/harvester/scene_entities.h b/engines/harvester/scene_entities.h
index ee026d1eb37..480b3740af5 100644
--- a/engines/harvester/scene_entities.h
+++ b/engines/harvester/scene_entities.h
@@ -63,6 +63,7 @@ private:
static Common::Rect getSceneRegionBounds(const RegionRecord ®ion);
static bool applyRoomNpcPlacement(Entity &entity, const NpcRecord &npc);
static void configureRoomNpcAnimation(Entity &entity, const NpcRecord &npc, bool preservedCorpse);
+ Entity *createSceneMonsterEntity(const MonsterRecord &monster);
RoomSetupState &_state;
Script *_script;
Commit: db94aa0a4ed73dbda1d3a1ac99699b2d9e8b5b10
https://github.com/scummvm/scummvm/commit/db94aa0a4ed73dbda1d3a1ac99699b2d9e8b5b10
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Share region entity construction
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/scene_entities.cpp
engines/harvester/scene_entities.h
diff --git a/engines/harvester/scene_entities.cpp b/engines/harvester/scene_entities.cpp
index ea36d0bc160..fef3d4a21f6 100644
--- a/engines/harvester/scene_entities.cpp
+++ b/engines/harvester/scene_entities.cpp
@@ -545,18 +545,12 @@ Common::Rect SceneEntities::getSceneRegionBounds(const RegionRecord ®ion) {
return Common::Rect();
}
-void SceneEntities::spawnSceneRegionEntityFromRecord(const RegionRecord ®ion) {
- if (!_entityManager)
- return;
-
- const Common::Rect bounds = getSceneRegionBounds(region);
- if (bounds.isEmpty())
- return;
-
+Entity *SceneEntities::createSceneRegionEntity(const RegionRecord ®ion,
+ const Common::Rect &bounds, const Common::String &diagnosticRoomName) {
Entity *entity = _entityManager->spawnSceneHotspotEntity(
region.regionName, bounds, (float)region.minZ);
if (!entity)
- return;
+ return nullptr;
entity->setClassId(kEntityClassRectHotspot19);
entity->setAnchorMode(kEntityAnchorTopLeft);
@@ -565,9 +559,21 @@ void SceneEntities::spawnSceneRegionEntityFromRecord(const RegionRecord ®ion)
entity->setHitTestMode(kEntityHitTestNone);
debugC(1, kDebugRoom,
"Harvester: scene region spawned room='%s' region='%s' class=0x%x bounds=(%d,%d)-(%d,%d) z=[%d,%d] facing=%d cursor=%d action='%s'",
- region.roomName.c_str(), region.regionName.c_str(), entity->getClassId(),
+ diagnosticRoomName.c_str(), region.regionName.c_str(), entity->getClassId(),
bounds.left, bounds.top, bounds.right, bounds.bottom,
region.minZ, region.maxZ, region.desiredFacing, region.cursorEnabled, region.actionTag.c_str());
+ return entity;
+}
+
+void SceneEntities::spawnSceneRegionEntityFromRecord(const RegionRecord ®ion) {
+ if (!_entityManager)
+ return;
+
+ const Common::Rect bounds = getSceneRegionBounds(region);
+ if (bounds.isEmpty())
+ return;
+
+ (void)createSceneRegionEntity(region, bounds, region.roomName);
}
bool SceneEntities::shouldSpawnRoomNpcEntity(const NpcRecord &npc) {
@@ -686,9 +692,7 @@ void SceneEntities::populateRoomRegions() {
if (regionBounds.isEmpty())
continue;
- Entity *entity = _entityManager->spawnSceneHotspotEntity(
- region.regionName, regionBounds, (float)region.minZ);
- if (!entity) {
+ if (!createSceneRegionEntity(region, regionBounds, _state.roomName)) {
debugC(1, kDebugRoom,
"Harvester: scene region skipped room='%s' region='%s' bounds=(%d,%d)-(%d,%d) z=[%d,%d]",
_state.roomName.c_str(), region.regionName.c_str(),
@@ -696,17 +700,6 @@ void SceneEntities::populateRoomRegions() {
region.minZ, region.maxZ);
continue;
}
-
- entity->setClassId(kEntityClassRectHotspot19);
- entity->setAnchorMode(kEntityAnchorTopLeft);
- entity->setZExtent((float)MAX(0, region.maxZ - region.minZ));
- if (!region.cursorEnabled)
- entity->setHitTestMode(kEntityHitTestNone);
- debugC(1, kDebugRoom,
- "Harvester: scene region spawned room='%s' region='%s' class=0x%x bounds=(%d,%d)-(%d,%d) z=[%d,%d] facing=%d cursor=%d action='%s'",
- _state.roomName.c_str(), region.regionName.c_str(), entity->getClassId(),
- regionBounds.left, regionBounds.top, regionBounds.right, regionBounds.bottom,
- region.minZ, region.maxZ, region.desiredFacing, region.cursorEnabled, region.actionTag.c_str());
}
}
diff --git a/engines/harvester/scene_entities.h b/engines/harvester/scene_entities.h
index 480b3740af5..9bcc84f5679 100644
--- a/engines/harvester/scene_entities.h
+++ b/engines/harvester/scene_entities.h
@@ -61,6 +61,8 @@ private:
bool isInteractiveSceneHotspot(const ObjectRecord &object) const;
EntityClass resolveSceneObjectClassLocal(const ObjectRecord &object, const Entity *entity) const;
static Common::Rect getSceneRegionBounds(const RegionRecord ®ion);
+ Entity *createSceneRegionEntity(const RegionRecord ®ion,
+ const Common::Rect &bounds, const Common::String &diagnosticRoomName);
static bool applyRoomNpcPlacement(Entity &entity, const NpcRecord &npc);
static void configureRoomNpcAnimation(Entity &entity, const NpcRecord &npc, bool preservedCorpse);
Entity *createSceneMonsterEntity(const MonsterRecord &monster);
Commit: 88ff885adbbc01c82311bccf9b9dc06af4d6c1a3
https://github.com/scummvm/scummvm/commit/88ff885adbbc01c82311bccf9b9dc06af4d6c1a3
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Move inspect text rendering into RoomPresentation
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.cpp
engines/harvester/input.cpp
engines/harvester/room_presentation.cpp
engines/harvester/room_presentation.h
engines/harvester/room_support.h
engines/harvester/scene.cpp
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index e88d6ed5eee..e76fdfcebe8 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -74,10 +74,6 @@ static const char *const kTownMapBitmapPaths[] = {
};
static const int kCursorSequence7 = 7;
-static const int kIdentTextboxX = 177;
-static const int kIdentTextboxY = 85;
-static const int kIdentTextboxTextInsetX = 10;
-static const int kIdentTextboxTextInsetY = 5;
static const int kNativeIdentTextLineSpacing = 3;
static const char *const kPlayerActorEntityName = "PLAYER";
// ramp_palette_brightness (0x23a30) waits four DOS centiseconds per step.
@@ -102,8 +98,6 @@ static const uint32 kTransitionWaitFrameMinMs = 120;
static const int kTownMapEdgeThreshold = 9;
static const int kTownMapCursorHitExtent = 5;
-static const byte kIdentTextColor = 0xd3;
-static const byte kShadowColor = 0;
static const byte kTownMapLabelColor = 0x28;
static const int kCursorSequenceWalk = 0;
@@ -272,13 +266,6 @@ void logScenePaletteSummary(const char *label, const SceneState &scene, float br
label, scene.state.roomName.c_str(), scene.state.palettePath.c_str(), (double)brightness);
}
-static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
- if (!bitmap.isValid())
- return;
-
- screen.copyRectToSurface(bitmap.pixels.data(), bitmap.width, x, y, bitmap.width, bitmap.height);
-}
-
bool captureScreenBackdrop(const Graphics::Screen &screen, IndexedBitmap &bitmap) {
if (screen.w <= 0 || screen.h <= 0 || screen.format.bytesPerPixel != 1)
return false;
@@ -292,35 +279,6 @@ bool captureScreenBackdrop(const Graphics::Screen &screen, IndexedBitmap &bitmap
return true;
}
-static void drawShadowedString(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
- int x, int y, int width, byte color, Graphics::TextAlign align = Graphics::kTextAlignLeft) {
- font.drawString(&screen, text, x + 1, y + 1, width, kShadowColor, align);
- font.drawString(&screen, text, x, y, width, color, align);
-}
-
-static void drawWrappedShadowedText(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
- int x, int y, int width, byte color) {
- Common::Array<Common::String> lines;
- font.wordWrapText(text, width, lines);
-
- const int lineHeight = font.getFontHeight() + 2;
- for (uint i = 0; i < lines.size(); ++i)
- drawShadowedString(screen, font, lines[i], x, y + i * lineHeight, width, color);
-}
-
-static void drawWrappedText(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
- int x, int y, int width, byte color, int lineSpacing, bool useCftCharacterWrapping = false) {
- Common::Array<Common::String> lines;
- if (useCftCharacterWrapping)
- wrapCftTextByCharacterCount(font, text, width, lines);
- else
- font.wordWrapText(text, width, lines);
-
- const int lineHeight = font.getFontHeight() + lineSpacing;
- for (uint i = 0; i < lines.size(); ++i)
- font.drawString(&screen, lines[i], x, y + i * lineHeight, width, color);
-}
-
static void setScaledPalette(Graphics::Screen &screen, const byte *palette, float brightness) {
byte scaledPalette[256 * 3];
const float gammaBrightness = g_engine ? g_engine->getGammaBrightnessScale() : 1.0f;
@@ -614,44 +572,6 @@ static const NpcRecord *findRoomNpcAtPoint(HarvesterEngine &engine,
return npc;
}
-const IndexedBitmap *resolveInspectTextboxBitmap(const Art &art, const ResolvedText &text) {
- if (text.boxName.equalsIgnoreCase("BOX1"))
- return art.getTextboxBitmap(0);
- if (text.boxName.equalsIgnoreCase("BOX2"))
- return art.getTextboxBitmap(1);
- if (text.boxName.equalsIgnoreCase("BOX3"))
- return art.getTextboxBitmap(2);
- if (text.boxName.equalsIgnoreCase("BOX4"))
- return art.getTextboxBitmap(3);
-
- return nullptr;
-}
-
-void drawRoomInspectText(Graphics::Screen &screen, const Art &art, const Graphics::Font &font,
- const ResolvedText &inspectText, bool useNativeFont) {
- const IndexedBitmap *textbox = resolveInspectTextboxBitmap(art, inspectText);
- if (!textbox || !textbox->isValid())
- return;
-
- blitBitmap(screen, *textbox, kIdentTextboxX, kIdentTextboxY);
- if (useNativeFont) {
- drawWrappedText(screen, font, inspectText.value,
- kIdentTextboxX + kIdentTextboxTextInsetX,
- kIdentTextboxY + kIdentTextboxTextInsetY,
- MAX<int>(0, (int)textbox->width - 2),
- 0,
- kNativeIdentTextLineSpacing,
- true);
- return;
- }
-
- drawWrappedShadowedText(screen, font, inspectText.value,
- kIdentTextboxX + kIdentTextboxTextInsetX,
- kIdentTextboxY + kIdentTextboxTextInsetY,
- MAX<int>(0, (int)textbox->width - (kIdentTextboxTextInsetX + 2)),
- kIdentTextColor);
-}
-
static bool suppressesInitialObjectInspectGate(const ObjectRecord &object) {
// Native HARVEST.SCR uses ident key X as a no-text sentinel.
return object.identTextKey.equalsIgnoreCase("X");
@@ -1278,7 +1198,7 @@ Common::Error Flow::runDemoEnding() {
setScaledPalette(*screen, palette, kPaletteBrightnessBlack);
screen->fillRect(Common::Rect(0, 0, screen->w, screen->h), 0);
- blitBitmap(*screen, bitmap, 0, 0);
+ RoomPresentation::blitBitmap(*screen, bitmap, 0, 0);
screen->makeAllDirty();
screen->update();
@@ -1347,9 +1267,9 @@ Common::Error Flow::runDemoIntroduction() {
entityManager->hideCursor();
setScaledPalette(*screen, palette, kPaletteBrightnessBlack);
screen->fillRect(Common::Rect(0, 0, screen->w, screen->h), 0);
- blitBitmap(*screen, bitmap, 0, 0);
+ RoomPresentation::blitBitmap(*screen, bitmap, 0, 0);
blitTransparentBitmap(*screen, art->getLogoBitmap(), 160, 0);
- drawWrappedText(*screen, font, kDemoIntroductionText, 90, 200, 420, 0xce,
+ RoomPresentation::drawWrappedText(*screen, font, kDemoIntroductionText, 90, 200, 420, 0xce,
kNativeIdentTextLineSpacing);
screen->makeAllDirty();
screen->update();
@@ -1528,9 +1448,9 @@ Common::Error Flow::runTownMapSelector(const Common::String &mapEntryName,
if (needsRedraw) {
setScaledPalette(*screen, palette, paletteBrightness);
screen->fillRect(screen->getBounds(), 0);
- blitBitmap(*screen, panels[(uint)currentPanel], 0, 0);
+ RoomPresentation::blitBitmap(*screen, panels[(uint)currentPanel], 0, 0);
if (hoveredLocation) {
- drawShadowedString(*screen, *font, hoveredLocation->labelText,
+ RoomPresentation::drawShadowedString(*screen, *font, hoveredLocation->labelText,
hoveredLocation->labelX, hoveredLocation->labelY, screen->w, kTownMapLabelColor);
}
if (EntityManager *entityManager = _engine.getRuntimeEntities())
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index 6029618b424..408f298420d 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -546,7 +546,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
const bool unlocksAfterInitialExamine =
unlocksRoomObjectInteractionAfterInitialExamine(*clickedObject, *_engine.getScript());
const bool canShowInspectText =
- hasInspectText && resolveInspectTextboxBitmap(_art, resolvedInspectText);
+ hasInspectText && RoomPresentation::resolveInspectTextboxBitmap(_art, resolvedInspectText);
if (!clickedObject->identShown && unlocksAfterInitialExamine) {
clickedObject->identShown = true;
_engine.getScript()->markObjectIdentShown(*clickedObject);
diff --git a/engines/harvester/room_presentation.cpp b/engines/harvester/room_presentation.cpp
index 1807e9f44f0..936a77c136f 100644
--- a/engines/harvester/room_presentation.cpp
+++ b/engines/harvester/room_presentation.cpp
@@ -30,6 +30,7 @@
#include "graphics/fontman.h"
#include "graphics/framelimiter.h"
#include "harvester/art.h"
+#include "harvester/cft_font.h"
#include "harvester/detection.h"
#include "harvester/entity.h"
#include "harvester/flow.h"
@@ -43,6 +44,13 @@ namespace Harvester {
static const float kNormalPaletteBrightness = 1.0f;
static const float kDimPaletteBrightness = 0.6f;
+static const int kIdentTextboxX = 177;
+static const int kIdentTextboxY = 85;
+static const int kIdentTextboxTextInsetX = 10;
+static const int kIdentTextboxTextInsetY = 5;
+static const byte kIdentTextColor = 0xd3;
+static const byte kShadowColor = 0;
+static const int kNativeIdentTextLineSpacing = 3;
static const char *const kPlayerActorEntityName = "PLAYER";
static const int kRoomDebugLabelPaddingX = 3;
static const int kRoomDebugLabelPaddingY = 2;
@@ -367,6 +375,80 @@ void RoomPresentation::drawRoomScene(HarvesterEngine &engine, Graphics::Screen &
drawTimerDebugOverlay(engine, screen, scene);
}
+void RoomPresentation::blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y) {
+ if (!bitmap.isValid())
+ return;
+
+ screen.copyRectToSurface(bitmap.pixels.data(), bitmap.width, x, y, bitmap.width, bitmap.height);
+}
+
+void RoomPresentation::drawShadowedString(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
+ int x, int y, int width, byte color, Graphics::TextAlign align) {
+ font.drawString(&screen, text, x + 1, y + 1, width, kShadowColor, align);
+ font.drawString(&screen, text, x, y, width, color, align);
+}
+
+static void drawWrappedShadowedText(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
+ int x, int y, int width, byte color) {
+ Common::Array<Common::String> lines;
+ font.wordWrapText(text, width, lines);
+
+ const int lineHeight = font.getFontHeight() + 2;
+ for (uint i = 0; i < lines.size(); ++i)
+ RoomPresentation::drawShadowedString(screen, font, lines[i], x, y + i * lineHeight, width, color);
+}
+
+void RoomPresentation::drawWrappedText(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
+ int x, int y, int width, byte color, int lineSpacing, bool useCftCharacterWrapping) {
+ Common::Array<Common::String> lines;
+ if (useCftCharacterWrapping)
+ wrapCftTextByCharacterCount(font, text, width, lines);
+ else
+ font.wordWrapText(text, width, lines);
+
+ const int lineHeight = font.getFontHeight() + lineSpacing;
+ for (uint i = 0; i < lines.size(); ++i)
+ font.drawString(&screen, lines[i], x, y + i * lineHeight, width, color);
+}
+
+const IndexedBitmap *RoomPresentation::resolveInspectTextboxBitmap(const Art &art, const ResolvedText &text) {
+ if (text.boxName.equalsIgnoreCase("BOX1"))
+ return art.getTextboxBitmap(0);
+ if (text.boxName.equalsIgnoreCase("BOX2"))
+ return art.getTextboxBitmap(1);
+ if (text.boxName.equalsIgnoreCase("BOX3"))
+ return art.getTextboxBitmap(2);
+ if (text.boxName.equalsIgnoreCase("BOX4"))
+ return art.getTextboxBitmap(3);
+
+ return nullptr;
+}
+
+void RoomPresentation::drawRoomInspectText(Graphics::Screen &screen, const Art &art, const Graphics::Font &font,
+ const ResolvedText &inspectText, bool useNativeFont) {
+ const IndexedBitmap *textbox = resolveInspectTextboxBitmap(art, inspectText);
+ if (!textbox || !textbox->isValid())
+ return;
+
+ blitBitmap(screen, *textbox, kIdentTextboxX, kIdentTextboxY);
+ if (useNativeFont) {
+ drawWrappedText(screen, font, inspectText.value,
+ kIdentTextboxX + kIdentTextboxTextInsetX,
+ kIdentTextboxY + kIdentTextboxTextInsetY,
+ MAX<int>(0, (int)textbox->width - 2),
+ 0,
+ kNativeIdentTextLineSpacing,
+ true);
+ return;
+ }
+
+ drawWrappedShadowedText(screen, font, inspectText.value,
+ kIdentTextboxX + kIdentTextboxTextInsetX,
+ kIdentTextboxY + kIdentTextboxTextInsetY,
+ MAX<int>(0, (int)textbox->width - (kIdentTextboxTextInsetX + 2)),
+ kIdentTextColor);
+}
+
RoomPresentation::RoomPresentation(HarvesterEngine &engine, SceneState &scene,
const Art *art, const Graphics::Font *inspectFont, bool useNativeInspectFont)
: _engine(engine), _scene(scene), _art(art), _inspectFont(inspectFont),
diff --git a/engines/harvester/room_presentation.h b/engines/harvester/room_presentation.h
index 577da6b4fe3..008531dbe41 100644
--- a/engines/harvester/room_presentation.h
+++ b/engines/harvester/room_presentation.h
@@ -23,10 +23,10 @@
#define HARVESTER_ROOM_PRESENTATION_H
#include "common/error.h"
+#include "graphics/font.h"
#include "harvester/script.h"
namespace Graphics {
-class Font;
class Screen;
}
@@ -66,6 +66,15 @@ public:
static void drawRoomScene(HarvesterEngine &engine, Graphics::Screen &screen,
const SceneState &scene, float brightness);
+ static void blitBitmap(Graphics::Screen &screen, const IndexedBitmap &bitmap, int x, int y);
+ static void drawShadowedString(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
+ int x, int y, int width, byte color, Graphics::TextAlign align = Graphics::kTextAlignLeft);
+ static void drawWrappedText(Graphics::Screen &screen, const Graphics::Font &font, const Common::String &text,
+ int x, int y, int width, byte color, int lineSpacing, bool useCftCharacterWrapping = false);
+ static const IndexedBitmap *resolveInspectTextboxBitmap(const Art &art, const ResolvedText &text);
+ static void drawRoomInspectText(Graphics::Screen &screen, const Art &art, const Graphics::Font &font,
+ const ResolvedText &inspectText, bool useNativeFont);
+
bool captureDialogueBackdrop(IndexedBitmap &dialogueBackdrop);
Common::Error applyLightingCommand(StartupLightingCommand lightingCommand);
Common::Error runModalShowText(const ResolvedText &modalText, Flow &flow);
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index b8b110a4a0a..9bc604d253a 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -79,9 +79,6 @@ const RegionRecord *findSceneRegionByName(const Common::Array<RegionRecord> ®
const Common::String ®ionName);
ObjectRecord *findSceneObjectByName(Common::Array<ObjectRecord> &objects,
const Common::String &objectName);
-const IndexedBitmap *resolveInspectTextboxBitmap(const Art &art, const ResolvedText &text);
-void drawRoomInspectText(Graphics::Screen &screen, const Art &art, const Graphics::Font &font,
- const ResolvedText &inspectText, bool useNativeFont);
bool unlocksRoomObjectInteractionAfterInitialExamine(const ObjectRecord &object,
Script &script);
bool doesPlayerFacingMatchRegion(int playerFacing, const RegionRecord ®ion);
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index 9d59fd9fde7..b2de54442b2 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -507,12 +507,12 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
}
if (_presentationState.showingInspectText) {
- drawRoomInspectText(*activeScreen, *_view.art, *_view.inspectFont, _presentationState.inspectText, _view.useNativeInspectFont);
+ RoomPresentation::drawRoomInspectText(*activeScreen, *_view.art, *_view.inspectFont, _presentationState.inspectText, _view.useNativeInspectFont);
if (!_presentationState.currentInteractionPromptText.empty())
drawRoomPrompt(*activeScreen, *_view.promptFont,
_presentationState.currentInteractionPromptText, _view.useNativePromptFont);
} else if (!_presentationState.combatLoadoutStatusText.value.empty()) {
- drawRoomInspectText(*activeScreen, *_view.art, *_view.inspectFont, _presentationState.combatLoadoutStatusText,
+ RoomPresentation::drawRoomInspectText(*activeScreen, *_view.art, *_view.inspectFont, _presentationState.combatLoadoutStatusText,
_view.useNativeInspectFont);
} else if (!inventoryTooltipText.empty()) {
drawInventoryTooltip(*activeScreen, *_view.inventoryTooltipFont, inventoryTooltipText);
Commit: 9f90244baac05e6b2d1617c39b3605a293b663ee
https://github.com/scummvm/scummvm/commit/9f90244baac05e6b2d1617c39b3605a293b663ee
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:07-04:00
Commit Message:
HARVESTER: Move scene record lookups into SceneEntities
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.cpp
engines/harvester/input.cpp
engines/harvester/interaction.cpp
engines/harvester/room_support.h
engines/harvester/scene.cpp
engines/harvester/scene_entities.cpp
engines/harvester/scene_entities.h
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index e76fdfcebe8..a43ae5f9721 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -425,36 +425,6 @@ bool shouldRunStartupRoomProbe() {
ConfMan.getBool("harvester_debug_probe_startup_room");
}
-const ObjectRecord *findSceneObjectByName(const Common::Array<ObjectRecord> &objects,
- const Common::String &objectName) {
- for (const ObjectRecord &object : objects) {
- if (object.objectName.equalsIgnoreCase(objectName))
- return &object;
- }
-
- return nullptr;
-}
-
-const RegionRecord *findSceneRegionByName(const Common::Array<RegionRecord> ®ions,
- const Common::String ®ionName) {
- for (const RegionRecord ®ion : regions) {
- if (region.regionName.equalsIgnoreCase(regionName))
- return ®ion;
- }
-
- return nullptr;
-}
-
-static const NpcRecord *findSceneNpcByName(const Common::Array<NpcRecord> &npcs,
- const Common::String &npcName) {
- for (const NpcRecord &npc : npcs) {
- if (npc.npcName.equalsIgnoreCase(npcName))
- return &npc;
- }
-
- return nullptr;
-}
-
static bool canTalkToRoomNpc(HarvesterEngine &engine, const NpcRecord &npc,
const DialogueSystem *dialogue) {
Script *script = engine.getScript();
@@ -464,16 +434,6 @@ static bool canTalkToRoomNpc(HarvesterEngine &engine, const NpcRecord &npc,
return dialogue && dialogue->hasRoomNpcHandler(npc.npcName);
}
-ObjectRecord *findSceneObjectByName(Common::Array<ObjectRecord> &objects,
- const Common::String &objectName) {
- for (ObjectRecord &object : objects) {
- if (object.objectName.equalsIgnoreCase(objectName))
- return &object;
- }
-
- return nullptr;
-}
-
static const ObjectRecord *findRoomObjectAtPoint(HarvesterEngine &engine,
const Common::Array<ObjectRecord> &sceneObjects, const Common::Point &point) {
EntityManager *entityManager = engine.getRuntimeEntities();
@@ -539,7 +499,7 @@ static const RegionRecord *findRoomRegionAtPoint(HarvesterEngine &engine,
if (!topEntity)
return nullptr;
- return findSceneRegionByName(sceneRegions, topEntity->getName());
+ return SceneEntities::findSceneRegionByName(sceneRegions, topEntity->getName());
}
static const Entity *findRoomPlayerAtPoint(HarvesterEngine &engine, const Common::Point &point) {
@@ -565,7 +525,7 @@ static const NpcRecord *findRoomNpcAtPoint(HarvesterEngine &engine,
if (!entity || entity->getClassId() != kEntityClassNpc)
return nullptr;
- const NpcRecord *npc = findSceneNpcByName(sceneNpcs, entity->getName());
+ const NpcRecord *npc = SceneEntities::findSceneNpcByName(sceneNpcs, entity->getName());
if (!npc || !canTalkToRoomNpc(engine, *npc, dialogue))
return nullptr;
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index 408f298420d..dee80e80534 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -34,6 +34,7 @@
#include "harvester/room_presentation.h"
#include "harvester/scene.h"
#include "harvester/room_support.h"
+#include "harvester/scene_entities.h"
namespace Harvester {
@@ -400,7 +401,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
}
}
}
- clickHoverState.object = findSceneObjectByName(_scene.sceneObjects, itemTarget->getName());
+ clickHoverState.object = SceneEntities::findSceneObjectByName(_scene.sceneObjects, itemTarget->getName());
}
debugC(1, kDebugRoom,
"Harvester: room click room='%s' mouse=(%d,%d) object='%s' npc='%s' region='%s' cursor_sequence=%d prompt='%s'",
@@ -434,7 +435,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
}
ObjectRecord *roomTarget = clickHoverState.object
- ? findSceneObjectByName(_scene.sceneObjects, clickHoverState.object->objectName)
+ ? SceneEntities::findSceneObjectByName(_scene.sceneObjects, clickHoverState.object->objectName)
: nullptr;
if (roomTarget) {
Common::Error interactionError =
@@ -502,7 +503,7 @@ InputResult Input::handleLeftButtonDown(bool &needsRedraw) {
return InputResult();
}
ObjectRecord *clickedObject = hoverState.object
- ? findSceneObjectByName(_scene.sceneObjects, hoverState.object->objectName)
+ ? SceneEntities::findSceneObjectByName(_scene.sceneObjects, hoverState.object->objectName)
: nullptr;
if (!clickedObject) {
_session.clearPendingRegionInteraction();
diff --git a/engines/harvester/interaction.cpp b/engines/harvester/interaction.cpp
index 09bd3be59c9..a5f33947652 100644
--- a/engines/harvester/interaction.cpp
+++ b/engines/harvester/interaction.cpp
@@ -111,7 +111,7 @@ void ItemInteractions::clearCarriedRoomItem() {
}
void ItemInteractions::hideSceneObject(const Common::String &objectName, const Common::String *ownerOrRoom) {
- ObjectRecord *sceneObject = findSceneObjectByName(_scene.sceneObjects, objectName);
+ ObjectRecord *sceneObject = SceneEntities::findSceneObjectByName(_scene.sceneObjects, objectName);
if (!sceneObject)
return;
@@ -426,7 +426,7 @@ Common::Error Interaction::tryActivatePendingRegion(InventorySystem &inventory,
if (_pendingRegionName.empty() || !playerState.entity)
return Common::kNoError;
- const RegionRecord *region = findSceneRegionByName(_scene.sceneRegions, _pendingRegionName);
+ const RegionRecord *region = SceneEntities::findSceneRegionByName(_scene.sceneRegions, _pendingRegionName);
if (!region || !region->startEnabled) {
_pendingRegionName.clear();
return Common::kNoError;
@@ -464,7 +464,7 @@ Common::Error Interaction::tryActivatePassiveRegion(InventorySystem &inventory,
}
int Interaction::getPendingRegionFacing() const {
- const RegionRecord *pendingRegion = findSceneRegionByName(_scene.sceneRegions, _pendingRegionName);
+ const RegionRecord *pendingRegion = SceneEntities::findSceneRegionByName(_scene.sceneRegions, _pendingRegionName);
return pendingRegion && pendingRegion->startEnabled ? pendingRegion->desiredFacing : -1;
}
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index 9bc604d253a..df61c36b579 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -73,12 +73,6 @@ Common::Rect getRoomObjectHotspotBounds(const ObjectRecord &object);
bool shouldDisplaySceneAnimation(const AnimRecord &anim);
bool loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resources, SceneState &scene);
bool shouldRunStartupRoomProbe();
-const ObjectRecord *findSceneObjectByName(const Common::Array<ObjectRecord> &objects,
- const Common::String &objectName);
-const RegionRecord *findSceneRegionByName(const Common::Array<RegionRecord> ®ions,
- const Common::String ®ionName);
-ObjectRecord *findSceneObjectByName(Common::Array<ObjectRecord> &objects,
- const Common::String &objectName);
bool unlocksRoomObjectInteractionAfterInitialExamine(const ObjectRecord &object,
Script &script);
bool doesPlayerFacingMatchRegion(int playerFacing, const RegionRecord ®ion);
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index b2de54442b2..6b64240b16d 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -47,6 +47,7 @@
#include "harvester/input.h"
#include "harvester/room_presentation.h"
#include "harvester/room_support.h"
+#include "harvester/scene_entities.h"
namespace Harvester {
@@ -434,7 +435,7 @@ bool Scene::drawRoomFrame(bool &needsRedraw) {
return Common::String();
if (target == playerState.entity)
return Common::String(kPlayerInventoryLabel);
- if (const ObjectRecord *object = findSceneObjectByName(_scene.sceneObjects, target->getName()))
+ if (const ObjectRecord *object = SceneEntities::findSceneObjectByName(_scene.sceneObjects, target->getName()))
return _engine.getScript()->resolveObjectLabel(*object);
for (const NpcRecord &npc : _scene.state.roomNpcs) {
if (npc.npcName.equalsIgnoreCase(target->getName()))
diff --git a/engines/harvester/scene_entities.cpp b/engines/harvester/scene_entities.cpp
index fef3d4a21f6..3e90b24aa81 100644
--- a/engines/harvester/scene_entities.cpp
+++ b/engines/harvester/scene_entities.cpp
@@ -35,19 +35,51 @@ static bool sameRect(const Common::Rect &lhs, const Common::Rect &rhs) {
lhs.right == rhs.right && lhs.bottom == rhs.bottom;
}
-static const AnimRecord *findRoomAnimByNameConst(const Common::Array<AnimRecord> &anims, const Common::String &animName) {
- for (const AnimRecord &anim : anims) {
- if (anim.animName.equalsIgnoreCase(animName))
- return &anim;
+const ObjectRecord *SceneEntities::findSceneObjectByName(const Common::Array<ObjectRecord> &objects,
+ const Common::String &objectName) {
+ for (const ObjectRecord &object : objects) {
+ if (object.objectName.equalsIgnoreCase(objectName))
+ return &object;
+ }
+
+ return nullptr;
+}
+
+const RegionRecord *SceneEntities::findSceneRegionByName(const Common::Array<RegionRecord> ®ions,
+ const Common::String ®ionName) {
+ for (const RegionRecord ®ion : regions) {
+ if (region.regionName.equalsIgnoreCase(regionName))
+ return ®ion;
}
+
return nullptr;
}
-static const NpcRecord *findRoomNpcByNameConst(const Common::Array<NpcRecord> &npcs, const Common::String &npcName) {
+const NpcRecord *SceneEntities::findSceneNpcByName(const Common::Array<NpcRecord> &npcs,
+ const Common::String &npcName) {
for (const NpcRecord &npc : npcs) {
if (npc.npcName.equalsIgnoreCase(npcName))
return &npc;
}
+
+ return nullptr;
+}
+
+ObjectRecord *SceneEntities::findSceneObjectByName(Common::Array<ObjectRecord> &objects,
+ const Common::String &objectName) {
+ for (ObjectRecord &object : objects) {
+ if (object.objectName.equalsIgnoreCase(objectName))
+ return &object;
+ }
+
+ return nullptr;
+}
+
+static const AnimRecord *findRoomAnimByNameConst(const Common::Array<AnimRecord> &anims, const Common::String &animName) {
+ for (const AnimRecord &anim : anims) {
+ if (anim.animName.equalsIgnoreCase(animName))
+ return &anim;
+ }
return nullptr;
}
@@ -270,7 +302,7 @@ bool SceneEntities::reconcileSceneEntitiesInPlace(const SceneState &previousScen
for (const NpcRecord &npc : _state.roomNpcs) {
const NpcRecord *updatedNpc =
- findRoomNpcByNameConst(updatedState.roomNpcs, npc.npcName);
+ findSceneNpcByName(updatedState.roomNpcs, npc.npcName);
const bool keepCurrentRoomDeathEntity =
!updatedNpc &&
isRetainedCurrentRoomNpcDeathRecord(npc) &&
@@ -298,7 +330,7 @@ bool SceneEntities::reconcileSceneEntitiesInPlace(const SceneState &previousScen
? _entityManager->findSceneEntityByName(npc.npcName)
: nullptr;
const NpcRecord *previousNpc =
- findRoomNpcByNameConst(_state.roomNpcs, npc.npcName);
+ findSceneNpcByName(_state.roomNpcs, npc.npcName);
const bool keepQueuedDeathEntity =
entity &&
previousNpc &&
diff --git a/engines/harvester/scene_entities.h b/engines/harvester/scene_entities.h
index 9bcc84f5679..5d751fa5454 100644
--- a/engines/harvester/scene_entities.h
+++ b/engines/harvester/scene_entities.h
@@ -44,6 +44,15 @@ public:
void populateRoomMonsters();
void restoreRoomMonsterAnimations();
+ static const ObjectRecord *findSceneObjectByName(const Common::Array<ObjectRecord> &objects,
+ const Common::String &objectName);
+ static ObjectRecord *findSceneObjectByName(Common::Array<ObjectRecord> &objects,
+ const Common::String &objectName);
+ static const RegionRecord *findSceneRegionByName(const Common::Array<RegionRecord> ®ions,
+ const Common::String ®ionName);
+ static const NpcRecord *findSceneNpcByName(const Common::Array<NpcRecord> &npcs,
+ const Common::String &npcName);
+
void removeSceneEntityByName(const Common::String &entityName);
static Common::Rect getSceneObjectBounds(const ObjectRecord &object);
static Common::String resolveSceneObjectSpritePathLocal(const ObjectRecord &object);
Commit: fb53fc98380ae9e17538cd99559e8e1ad97871d6
https://github.com/scummvm/scummvm/commit/fb53fc98380ae9e17538cd99559e8e1ad97871d6
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:08-04:00
Commit Message:
HARVESTER: Move scene resource assembly into SceneEntities
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/art.cpp
engines/harvester/art.h
engines/harvester/flow.cpp
engines/harvester/room_support.h
engines/harvester/scene.cpp
engines/harvester/scene_entities.cpp
engines/harvester/scene_entities.h
diff --git a/engines/harvester/art.cpp b/engines/harvester/art.cpp
index 702c04b1966..63ec43b2851 100644
--- a/engines/harvester/art.cpp
+++ b/engines/harvester/art.cpp
@@ -93,6 +93,27 @@ static const char *const kAmmoIconPaths[] = {
} // End of anonymous namespace
+bool Art::loadPaletteResource(ResourceManager &resources, const Common::String &path, byte *dest) {
+ Common::Array<byte> data;
+ if (!resources.loadFile(path, data) || data.size() < 256 * 3)
+ return false;
+
+ memcpy(dest, data.data(), 256 * 3);
+
+ byte minValue = 0;
+ byte maxValue = 0;
+ getPaletteByteRange(dest, minValue, maxValue);
+ debugC(3, kDebugRoom,
+ "Harvester: decoded room palette '%s' bytes=%u range=[%u,%u] hash=%08x idx0=(%u,%u,%u) idx1=(%u,%u,%u) idx127=(%u,%u,%u) idx255=(%u,%u,%u)",
+ path.c_str(), (uint)data.size(), minValue, maxValue, hashPalette(dest),
+ dest[0], dest[1], dest[2],
+ dest[3], dest[4], dest[5],
+ dest[127 * 3], dest[127 * 3 + 1], dest[127 * 3 + 2],
+ dest[255 * 3], dest[255 * 3 + 1], dest[255 * 3 + 2]);
+
+ return true;
+}
+
bool Art::load(ResourceManager &resources) {
_waitFrames.clear();
_textboxes.clear();
diff --git a/engines/harvester/art.h b/engines/harvester/art.h
index 1b810560a21..47192e73ccd 100644
--- a/engines/harvester/art.h
+++ b/engines/harvester/art.h
@@ -36,6 +36,7 @@ class Art {
public:
bool load(ResourceManager &resources);
bool loadQuickTipsResources(ResourceManager &resources, bool useTextboxPanel);
+ static bool loadPaletteResource(ResourceManager &resources, const Common::String &path, byte *dest);
void drawWaitFrame(Graphics::Screen &screen) const;
const byte *getWaitPalette() const { return _waitPalette; }
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index a43ae5f9721..17d3b4c1058 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -241,26 +241,6 @@ static bool applyStartupActorPlacement(const RoomSetupState &state, Entity &enti
state.playerSpawnX, state.playerSpawnY, (float)state.playerSpawnZ, &state.entranceName);
}
-static void getPaletteByteRange(const byte *palette, byte &minValue, byte &maxValue) {
- minValue = 255;
- maxValue = 0;
-
- for (uint i = 0; i < 256 * 3; ++i) {
- minValue = MIN(minValue, palette[i]);
- maxValue = MAX(maxValue, palette[i]);
- }
-}
-
-static uint32 hashPalette(const byte *palette) {
- uint32 hash = 2166136261U;
- for (uint i = 0; i < 256 * 3; ++i) {
- hash ^= palette[i];
- hash *= 16777619U;
- }
-
- return hash;
-}
-
void logScenePaletteSummary(const char *label, const SceneState &scene, float brightness) {
debugC(2, kDebugRoom, "Harvester: %s room='%s' palette='%s' brightness=%.2f",
label, scene.state.roomName.c_str(), scene.state.palettePath.c_str(), (double)brightness);
@@ -294,34 +274,6 @@ static void setScaledDisplayPalette(Graphics::Screen &screen, const byte *palett
screen.setPalette(scaledPalette);
}
-static bool loadPaletteResource(ResourceManager &resources, const Common::String &path, byte *dest) {
- Common::Array<byte> data;
- if (!resources.loadFile(path, data) || data.size() < 256 * 3)
- return false;
-
- memcpy(dest, data.data(), 256 * 3);
-
- byte minValue = 0;
- byte maxValue = 0;
- getPaletteByteRange(dest, minValue, maxValue);
- debugC(3, kDebugRoom,
- "Harvester: decoded room palette '%s' bytes=%u range=[%u,%u] hash=%08x idx0=(%u,%u,%u) idx1=(%u,%u,%u) idx127=(%u,%u,%u) idx255=(%u,%u,%u)",
- path.c_str(), (uint)data.size(), minValue, maxValue, hashPalette(dest),
- dest[0], dest[1], dest[2],
- dest[3], dest[4], dest[5],
- dest[127 * 3], dest[127 * 3 + 1], dest[127 * 3 + 2],
- dest[255 * 3], dest[255 * 3 + 1], dest[255 * 3 + 2]);
-
- return true;
-}
-
-Common::Rect getRoomObjectHotspotBounds(const ObjectRecord &object) {
- if (object.boundsX2 > object.currentX && object.boundsY2 > object.currentY)
- return Common::Rect(object.currentX, object.currentY, object.boundsX2 + 1, object.boundsY2 + 1);
-
- return Common::Rect();
-}
-
static Common::Rect getRegionBounds(const RegionRecord ®ion) {
if (region.right > region.left && region.bottom > region.top)
return Common::Rect(region.left, region.top, region.right, region.bottom);
@@ -329,17 +281,6 @@ static Common::Rect getRegionBounds(const RegionRecord ®ion) {
return Common::Rect();
}
-Common::String resolveSceneObjectSpritePath(const ObjectRecord &object) {
- const bool atInitialPlacement = object.currentX == object.initialX &&
- object.currentY == object.initialY &&
- object.currentOwnerOrRoom.equalsIgnoreCase(object.initialOwnerOrRoom);
- if (!object.altSpritePath.empty() &&
- (!atInitialPlacement || object.currentOwnerOrRoom.equalsIgnoreCase("INVENTORY")))
- return object.altSpritePath;
-
- return object.spritePath;
-}
-
bool loadBitmapResource(ResourceManager &resources, const Common::String &path, IndexedBitmap &bitmap) {
Common::Array<byte> data;
if (!resources.loadFile(path, data) || data.size() < 12)
@@ -349,77 +290,6 @@ bool loadBitmapResource(ResourceManager &resources, const Common::String &path,
return decodeBitmap(data, bitmap);
}
-static void logSceneObjectSelection(const char *decision, const char *source, const ObjectRecord &object,
- const Common::String &detail = Common::String()) {
- const Common::Rect hotspotBounds = getRoomObjectHotspotBounds(object);
- const Common::String resolvedSpritePath = resolveSceneObjectSpritePath(object);
- debugC(3, kDebugScene,
- "Harvester: scene object %s source='%s' object='%s' owner='%s' visible=%d runtimeVisible=%d sprite='%s' alt='%s' resolved='%s' pos=(%d,%d,%d) bounds=(%d,%d)-(%d,%d) action='%s' detail='%s'",
- decision, source, object.objectName.c_str(), object.currentOwnerOrRoom.c_str(),
- object.visible, object.runtimeVisible, object.spritePath.c_str(), object.altSpritePath.c_str(),
- resolvedSpritePath.c_str(),
- object.currentX, object.currentY, object.currentZ,
- hotspotBounds.left, hotspotBounds.top, hotspotBounds.right, hotspotBounds.bottom,
- object.actionTag.c_str(), detail.c_str());
-}
-
-static bool shouldQueueSceneObject(const ObjectRecord &object) {
- return object.visible;
-}
-
-bool shouldDisplaySceneAnimation(const AnimRecord &anim) {
- return anim.active || anim.visible;
-}
-
-static void queueSceneObject(const char *source, const ObjectRecord &object,
- Common::Array<ObjectRecord> &sceneObjects) {
- if (!shouldQueueSceneObject(object)) {
- logSceneObjectSelection("skipped", source, object, object.visible ? "inactive" : "visible=0");
- return;
- }
-
- for (const ObjectRecord &sceneObject : sceneObjects) {
- if (sceneObject.currentOwnerOrRoom.equalsIgnoreCase(object.currentOwnerOrRoom) &&
- sceneObject.objectName.equalsIgnoreCase(object.objectName)) {
- logSceneObjectSelection("skipped", source, object, "duplicate owner/object");
- return;
- }
- }
-
- sceneObjects.push_back(object);
- logSceneObjectSelection("queued", source, object);
-}
-
-bool loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resources, SceneState &scene) {
- scene = SceneState();
- scene.state = state;
- scene.targetPaletteBrightness = state.paletteBrightness;
- if (!loadPaletteResource(resources, state.palettePath, scene.palette)) {
- return false;
- }
-
- Common::Array<ObjectRecord> sceneObjects;
- for (const ObjectRecord &object : state.roomObjects)
- queueSceneObject("room", object, sceneObjects);
- for (const ObjectRecord &object : state.activeObjects)
- queueSceneObject("active", object, sceneObjects);
-
- scene.sceneObjects = Common::move(sceneObjects);
- for (const AnimRecord &anim : state.roomAnimations) {
- if (shouldDisplaySceneAnimation(anim))
- scene.sceneAnimations.push_back(anim);
- }
- scene.sceneRegions = state.roomRegions;
-
- debugC(2, kDebugRoom,
- "Harvester: room scene loaded room='%s' objects=%u anims=%u npcs=%u monsters=%u timers=%u regions=%u",
- state.roomName.c_str(), (uint)scene.sceneObjects.size(), (uint)scene.sceneAnimations.size(),
- (uint)state.roomNpcs.size(), (uint)state.roomMonsters.size(),
- (uint)state.roomTimers.size(), (uint)scene.sceneRegions.size());
-
- return true;
-}
-
bool shouldRunStartupRoomProbe() {
return ConfMan.hasKey("harvester_debug_probe_startup_room") &&
ConfMan.getBool("harvester_debug_probe_startup_room");
@@ -701,7 +571,7 @@ RoomHoverState Flow::getRoomHoverState(const SceneState &scene) const {
static bool findRoomObjectProbePoint(HarvesterEngine &engine, const Common::Array<ObjectRecord> &sceneObjects,
const ObjectRecord &object, Common::Point &probePoint) {
- const Common::Rect bounds = getRoomObjectHotspotBounds(object);
+ const Common::Rect bounds = SceneEntities::getSceneObjectBounds(object);
if (bounds.isEmpty())
return false;
@@ -769,7 +639,7 @@ void Flow::logStartupRoomProbe(const SceneState &scene, const Common::String &en
}
for (const ObjectRecord &object : scene.sceneObjects) {
- if (getRoomObjectHotspotBounds(object).isEmpty())
+ if (SceneEntities::getSceneObjectBounds(object).isEmpty())
continue;
Common::Point probePoint;
@@ -864,7 +734,7 @@ static bool loadQuickTipsScene(HarvesterEngine &engine, SceneState &scene) {
if (!engine.getScript()->resolveRoomSetupState("START", state, *engine.getResources()))
return false;
- return loadRoomSceneResources(state, *engine.getResources(), scene);
+ return SceneEntities::loadRoomSceneResources(state, *engine.getResources(), scene);
}
static void renderQuickTipsScreen(HarvesterEngine &engine, const SceneState &scene,
@@ -1151,7 +1021,7 @@ Common::Error Flow::runDemoEnding() {
IndexedBitmap bitmap;
byte palette[256 * 3];
if (!loadBitmapResource(*resources, bitmapPath, bitmap) ||
- !loadPaletteResource(*resources, palettePath, palette)) {
+ !Art::loadPaletteResource(*resources, palettePath, palette)) {
warning("Harvester: unable to load DOS demo ending screen %d", screenNumber);
return Common::kReadingFailed;
}
@@ -1212,7 +1082,7 @@ Common::Error Flow::runDemoIntroduction() {
IndexedBitmap bitmap;
byte palette[256 * 3];
if (!loadBitmapResource(*resources, kDemoIntroductionBitmapPath, bitmap) ||
- !loadPaletteResource(*resources, kDemoIntroductionPalettePath, palette)) {
+ !Art::loadPaletteResource(*resources, kDemoIntroductionPalettePath, palette)) {
return Common::kReadingFailed;
}
@@ -1355,7 +1225,7 @@ Common::Error Flow::runTownMapSelector(const Common::String &mapEntryName,
: kTownMapNightPaletteBrightness;
byte palette[256 * 3];
- if (!loadPaletteResource(*resources, kTownMapPalettePath, palette))
+ if (!Art::loadPaletteResource(*resources, kTownMapPalettePath, palette))
return Common::kReadingFailed;
Common::Array<IndexedBitmap> panels;
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index df61c36b579..35f6b22dddd 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -69,9 +69,7 @@ bool applyRoomActorPlacement(const RoomSetupState &state, Entity &entity,
int centerX, int bottomY, float z, const Common::String *entranceName = nullptr);
void logScenePaletteSummary(const char *label, const SceneState &scene, float brightness);
bool captureScreenBackdrop(const Graphics::Screen &screen, IndexedBitmap &bitmap);
-Common::Rect getRoomObjectHotspotBounds(const ObjectRecord &object);
bool shouldDisplaySceneAnimation(const AnimRecord &anim);
-bool loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resources, SceneState &scene);
bool shouldRunStartupRoomProbe();
bool unlocksRoomObjectInteractionAfterInitialExamine(const ObjectRecord &object,
Script &script);
diff --git a/engines/harvester/scene.cpp b/engines/harvester/scene.cpp
index 6b64240b16d..baaac7fd858 100644
--- a/engines/harvester/scene.cpp
+++ b/engines/harvester/scene.cpp
@@ -976,7 +976,7 @@ Common::Error SceneRunner::runRoomLoop(Flow &flow, const Common::String &targetN
return transitionError;
SceneState scene;
- if (!loadRoomSceneResources(state, *_engine.getResources(), scene))
+ if (!SceneEntities::loadRoomSceneResources(state, *_engine.getResources(), scene))
return Common::kReadingFailed;
Graphics::Screen *screen = _engine.getScreen();
diff --git a/engines/harvester/scene_entities.cpp b/engines/harvester/scene_entities.cpp
index 3e90b24aa81..c01b91c5df5 100644
--- a/engines/harvester/scene_entities.cpp
+++ b/engines/harvester/scene_entities.cpp
@@ -21,7 +21,9 @@
#include "harvester/scene_entities.h"
+#include "harvester/art.h"
#include "harvester/detection.h"
+#include "harvester/resources.h"
#include "harvester/monster.h"
#include "harvester/player.h"
#include "harvester/combat.h"
@@ -172,6 +174,77 @@ SceneEntities::SceneEntities(RoomSetupState &state, Script *script, ResourceMana
_state.roomName.c_str(), _entityManager != nullptr);
}
+static void logSceneObjectSelection(const char *decision, const char *source, const ObjectRecord &object,
+ const Common::String &detail = Common::String()) {
+ const Common::Rect hotspotBounds = SceneEntities::getSceneObjectBounds(object);
+ const Common::String resolvedSpritePath = SceneEntities::resolveSceneObjectSpritePathLocal(object);
+ debugC(3, kDebugScene,
+ "Harvester: scene object %s source='%s' object='%s' owner='%s' visible=%d runtimeVisible=%d sprite='%s' alt='%s' resolved='%s' pos=(%d,%d,%d) bounds=(%d,%d)-(%d,%d) action='%s' detail='%s'",
+ decision, source, object.objectName.c_str(), object.currentOwnerOrRoom.c_str(),
+ object.visible, object.runtimeVisible, object.spritePath.c_str(), object.altSpritePath.c_str(),
+ resolvedSpritePath.c_str(),
+ object.currentX, object.currentY, object.currentZ,
+ hotspotBounds.left, hotspotBounds.top, hotspotBounds.right, hotspotBounds.bottom,
+ object.actionTag.c_str(), detail.c_str());
+}
+
+static bool shouldQueueSceneObject(const ObjectRecord &object) {
+ return object.visible;
+}
+
+bool shouldDisplaySceneAnimation(const AnimRecord &anim) {
+ return anim.active || anim.visible;
+}
+
+static void queueSceneObject(const char *source, const ObjectRecord &object,
+ Common::Array<ObjectRecord> &sceneObjects) {
+ if (!shouldQueueSceneObject(object)) {
+ logSceneObjectSelection("skipped", source, object, object.visible ? "inactive" : "visible=0");
+ return;
+ }
+
+ for (const ObjectRecord &sceneObject : sceneObjects) {
+ if (sceneObject.currentOwnerOrRoom.equalsIgnoreCase(object.currentOwnerOrRoom) &&
+ sceneObject.objectName.equalsIgnoreCase(object.objectName)) {
+ logSceneObjectSelection("skipped", source, object, "duplicate owner/object");
+ return;
+ }
+ }
+
+ sceneObjects.push_back(object);
+ logSceneObjectSelection("queued", source, object);
+}
+
+bool SceneEntities::loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resources, SceneState &scene) {
+ scene = SceneState();
+ scene.state = state;
+ scene.targetPaletteBrightness = state.paletteBrightness;
+ if (!Art::loadPaletteResource(resources, state.palettePath, scene.palette)) {
+ return false;
+ }
+
+ Common::Array<ObjectRecord> sceneObjects;
+ for (const ObjectRecord &object : state.roomObjects)
+ queueSceneObject("room", object, sceneObjects);
+ for (const ObjectRecord &object : state.activeObjects)
+ queueSceneObject("active", object, sceneObjects);
+
+ scene.sceneObjects = Common::move(sceneObjects);
+ for (const AnimRecord &anim : state.roomAnimations) {
+ if (shouldDisplaySceneAnimation(anim))
+ scene.sceneAnimations.push_back(anim);
+ }
+ scene.sceneRegions = state.roomRegions;
+
+ debugC(2, kDebugRoom,
+ "Harvester: room scene loaded room='%s' objects=%u anims=%u npcs=%u monsters=%u timers=%u regions=%u",
+ state.roomName.c_str(), (uint)scene.sceneObjects.size(), (uint)scene.sceneAnimations.size(),
+ (uint)state.roomNpcs.size(), (uint)state.roomMonsters.size(),
+ (uint)state.roomTimers.size(), (uint)scene.sceneRegions.size());
+
+ return true;
+}
+
bool SceneEntities::loadSceneResources(const RoomSetupState &state, SceneState &scene) const {
return _resources && loadRoomSceneResources(state, *_resources, scene);
}
@@ -741,7 +814,7 @@ void SceneEntities::populateRoomObjects(const Common::Array<ObjectRecord> &drawa
for (const ObjectRecord &object : drawableObjects) {
const Common::String spritePath = resolveSceneObjectSpritePathLocal(object);
- const Common::Rect hotspotBounds = getRoomObjectHotspotBounds(object);
+ const Common::Rect hotspotBounds = getSceneObjectBounds(object);
Entity *entity = createSceneObjectEntity(object, spritePath, hotspotBounds);
if (!entity) {
diff --git a/engines/harvester/scene_entities.h b/engines/harvester/scene_entities.h
index 5d751fa5454..c6ef70c4154 100644
--- a/engines/harvester/scene_entities.h
+++ b/engines/harvester/scene_entities.h
@@ -32,6 +32,7 @@ class SceneEntities {
public:
SceneEntities(RoomSetupState &state, Script *script, ResourceManager *resources, EntityManager *entityManager);
+ static bool loadRoomSceneResources(const RoomSetupState &state, ResourceManager &resources, SceneState &scene);
bool loadSceneResources(const RoomSetupState &state, SceneState &scene) const;
bool reconcileSceneEntitiesInPlace(const SceneState &previousScene,
RoomSetupState &updatedState, const SceneState &updatedScene);
Commit: bdb15ec5f3c36352984551f03bb0928024206031
https://github.com/scummvm/scummvm/commit/bdb15ec5f3c36352984551f03bb0928024206031
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:08-04:00
Commit Message:
HARVESTER: Move hover resolution into Input
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.cpp
engines/harvester/input.cpp
engines/harvester/input.h
engines/harvester/room_support.h
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 17d3b4c1058..99a8e1073a7 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -39,6 +39,7 @@
#include "harvester/detection.h"
#include "harvester/fst_player.h"
#include "harvester/harvester.h"
+#include "harvester/input.h"
#include "harvester/palette_utils.h"
#include "harvester/resources.h"
#include "harvester/entity.h"
@@ -101,12 +102,6 @@ static const int kTownMapCursorHitExtent = 5;
static const byte kTownMapLabelColor = 0x28;
static const int kCursorSequenceWalk = 0;
-static const int kCursorSequenceExamine = 1;
-static const int kCursorSequenceTalk = 2;
-static const int kCursorSequenceOperate = 4;
-static const int kCursorSequencePickup = 5;
-static const int kCursorSequenceTransition = 6;
-static const int kCursorSequenceNeutral = 7;
} // End of anonymous namespace
static int clampTownMapPanelIndex(int panelIndex) {
@@ -295,194 +290,6 @@ bool shouldRunStartupRoomProbe() {
ConfMan.getBool("harvester_debug_probe_startup_room");
}
-static bool canTalkToRoomNpc(HarvesterEngine &engine, const NpcRecord &npc,
- const DialogueSystem *dialogue) {
- Script *script = engine.getScript();
- if (!script || !script->isNamedNpcDeathTypeClear(npc.npcName))
- return false;
-
- return dialogue && dialogue->hasRoomNpcHandler(npc.npcName);
-}
-
-static const ObjectRecord *findRoomObjectAtPoint(HarvesterEngine &engine,
- const Common::Array<ObjectRecord> &sceneObjects, const Common::Point &point) {
- EntityManager *entityManager = engine.getRuntimeEntities();
- if (!entityManager)
- return nullptr;
-
- const Entity *topEntity = nullptr;
- const ObjectRecord *topObject = nullptr;
- int topDrawIndex = -1;
- for (const ObjectRecord &object : sceneObjects) {
- if (object.objectName.empty())
- continue;
-
- const Entity *entity = entityManager->findSceneEntityByName(object.objectName);
- if (!entity || !entity->hitTest(point))
- continue;
- if (entity->getClassId() == kEntityClassBackground ||
- entity->getClassId() == kEntityClassPlayer ||
- entity->getClassId() == kEntityClassRectHotspot19) {
- continue;
- }
- const int drawIndex = entityManager->findSceneEntityDrawIndexByName(entity->getName());
- if (drawIndex < 0)
- continue;
- const bool objectVisible = object.visible && object.runtimeVisible;
- const bool topObjectVisible = topObject && topObject->visible && topObject->runtimeVisible;
- if (!topEntity ||
- (objectVisible && !topObjectVisible) ||
- (objectVisible == topObjectVisible && drawIndex > topDrawIndex)) {
- topEntity = entity;
- topObject = &object;
- topDrawIndex = drawIndex;
- }
- }
- if (!topEntity)
- return nullptr;
-
- return topObject;
-}
-
-static const RegionRecord *findRoomRegionAtPoint(HarvesterEngine &engine,
- const Common::Array<RegionRecord> &sceneRegions, const Common::Point &point) {
- EntityManager *entityManager = engine.getRuntimeEntities();
- if (!entityManager)
- return nullptr;
-
- const Entity *topEntity = nullptr;
- int topDrawIndex = -1;
- for (const RegionRecord ®ion : sceneRegions) {
- const Entity *entity = entityManager->findSceneEntityByName(region.regionName);
- if (!entity || !entity->hitTest(point))
- continue;
- if (entity->getClassId() != kEntityClassRectHotspot19)
- continue;
- const int drawIndex = entityManager->findSceneEntityDrawIndexByName(entity->getName());
- if (drawIndex < 0)
- continue;
- if (!topEntity || drawIndex > topDrawIndex) {
- topEntity = entity;
- topDrawIndex = drawIndex;
- }
- }
- if (!topEntity)
- return nullptr;
-
- return SceneEntities::findSceneRegionByName(sceneRegions, topEntity->getName());
-}
-
-static const Entity *findRoomPlayerAtPoint(HarvesterEngine &engine, const Common::Point &point) {
- EntityManager *entityManager = engine.getRuntimeEntities();
- if (!entityManager)
- return nullptr;
-
- const Entity *entity = entityManager->findTopSceneEntityAt(point);
- if (!entity || entity->getClassId() != kEntityClassPlayer)
- return nullptr;
-
- return entity;
-}
-
-static const NpcRecord *findRoomNpcAtPoint(HarvesterEngine &engine,
- const Common::Array<NpcRecord> &sceneNpcs, const Common::Point &point,
- const DialogueSystem *dialogue) {
- EntityManager *entityManager = engine.getRuntimeEntities();
- if (!entityManager)
- return nullptr;
-
- const Entity *entity = entityManager->findTopSceneEntityAt(point);
- if (!entity || entity->getClassId() != kEntityClassNpc)
- return nullptr;
-
- const NpcRecord *npc = SceneEntities::findSceneNpcByName(sceneNpcs, entity->getName());
- if (!npc || !canTalkToRoomNpc(engine, *npc, dialogue))
- return nullptr;
-
- return npc;
-}
-
-static bool suppressesInitialObjectInspectGate(const ObjectRecord &object) {
- // Native HARVEST.SCR uses ident key X as a no-text sentinel.
- return object.identTextKey.equalsIgnoreCase("X");
-}
-
-static bool usesBareOperatePrompt(const ObjectRecord &object) {
- return object.objectName.equalsIgnoreCase("HAPPLY_HS") ||
- object.objectName.equalsIgnoreCase("KILL_STEPH_HS");
-}
-
-bool unlocksRoomObjectInteractionAfterInitialExamine(const ObjectRecord &object,
- Script &script) {
- if (suppressesInitialObjectInspectGate(object))
- return false;
-
- return object.operatable || script.isPickupObject(object);
-}
-
-static int resolveRoomObjectCursorSequence(const ObjectRecord &object, Script &script) {
- if (object.objectName.equalsIgnoreCase("EXIT_BM") || object.objectName.equalsIgnoreCase("EXIT_HS"))
- return kCursorSequenceTransition;
-
- ResolvedText inspectText;
- const bool pickupObject = script.isPickupObject(object);
- const bool pickupBlocked = pickupObject && script.isPickupBlockedByAction(object);
- if (!object.identShown && unlocksRoomObjectInteractionAfterInitialExamine(object, script))
- return kCursorSequenceExamine;
- if (pickupObject && !pickupBlocked)
- return kCursorSequencePickup;
- if (pickupBlocked)
- return kCursorSequenceExamine;
- if (object.operatable)
- return kCursorSequenceOperate;
- if (script.resolveObjectInspectText(object, inspectText))
- return kCursorSequenceExamine;
-
- if (script.hasObjectInteraction(object))
- return kCursorSequenceExamine;
-
- return kCursorSequenceNeutral;
-}
-
-static Common::String buildRoomObjectPrompt(const ObjectRecord &object, Script &script,
- int cursorSequence, const MenuTextConfig &menuTextConfig) {
- // Native room prompts come from explicit interaction metadata. Neutral scene sprites
- // should not surface synthetic "Examine <object id>" prompts or steal hover/click focus.
- if (cursorSequence == kCursorSequenceNeutral)
- return Common::String();
-
- const Common::String label = script.resolveObjectLabel(object);
- if (label.empty())
- return Common::String();
-
- if (cursorSequence == kCursorSequenceOperate) {
- if (usesBareOperatePrompt(object))
- return label;
- return Common::String::format("%s %s", menuTextConfig.operateVerb.c_str(), label.c_str());
- }
- if (cursorSequence == kCursorSequencePickup)
- return Common::String::format("%s %s", menuTextConfig.pickUpVerb.c_str(), label.c_str());
- if (cursorSequence == kCursorSequenceTalk)
- return Common::String::format("%s %s", menuTextConfig.talkToVerb.c_str(), label.c_str());
- if (cursorSequence == kCursorSequenceTransition)
- return Common::String::format("Go to %s", label.c_str());
-
- return Common::String::format("%s %s", menuTextConfig.examineTheVerb.c_str(), label.c_str());
-}
-
-static Common::String buildRoomNpcPrompt(const NpcRecord &npc,
- const MenuTextConfig &menuTextConfig) {
- Common::String label = !npc.entityInitArg.empty() ? npc.entityInitArg : npc.npcName;
- for (uint i = 0; i < label.size(); ++i) {
- if (label[i] == '_')
- label.setChar(' ', i);
- }
-
- if (label.empty())
- return Common::String();
- return Common::String::format("%s %s", menuTextConfig.talkToVerb.c_str(), label.c_str());
-}
-
bool doesPlayerFacingMatchRegion(int playerFacing, const RegionRecord ®ion) {
return region.desiredFacing < 0 || playerFacing == region.desiredFacing;
}
@@ -508,64 +315,8 @@ bool doesPlayerOverlapRegion(const Entity &playerEntity, const RegionRecord ®
return playerMaxZ >= region.minZ && region.maxZ >= (int)playerEntity.getZ();
}
-RoomHoverState resolveRoomHoverState(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<NpcRecord> &sceneNpcs,
- const Common::Array<RegionRecord> &sceneRegions, const Common::Point &mousePos,
- const MenuTextConfig &menuTextConfig, const DialogueSystem *dialogue) {
- RoomHoverState hoverState;
- EntityManager *entityManager = engine.getRuntimeEntities();
- if (const Entity *playerEntity = findRoomPlayerAtPoint(engine, mousePos)) {
- hoverState.playerEntity = playerEntity;
- hoverState.cursorSequence = kCursorSequenceExamine;
- return hoverState;
- }
- if (const NpcRecord *npc = findRoomNpcAtPoint(engine, sceneNpcs, mousePos, dialogue)) {
- hoverState.npc = npc;
- hoverState.cursorSequence = kCursorSequenceTalk;
- hoverState.promptText = buildRoomNpcPrompt(*npc, menuTextConfig);
- return hoverState;
- }
-
- Script *script = engine.getScript();
- if (!script)
- return hoverState;
- hoverState.object = findRoomObjectAtPoint(engine, sceneObjects, mousePos);
- hoverState.region = findRoomRegionAtPoint(engine, sceneRegions, mousePos);
- if (entityManager && hoverState.object && hoverState.region) {
- const int objectDrawIndex =
- entityManager->findSceneEntityDrawIndexByName(hoverState.object->objectName);
- const int regionDrawIndex =
- entityManager->findSceneEntityDrawIndexByName(hoverState.region->regionName);
- if (regionDrawIndex >= 0 && objectDrawIndex >= 0 && regionDrawIndex > objectDrawIndex)
- hoverState.object = nullptr;
- }
- if (hoverState.object) {
- hoverState.cursorSequence = resolveRoomObjectCursorSequence(*hoverState.object, *script);
- hoverState.promptText = buildRoomObjectPrompt(
- *hoverState.object, *script, hoverState.cursorSequence, menuTextConfig);
- if (hoverState.cursorSequence != kCursorSequenceNeutral || !hoverState.promptText.empty())
- return hoverState;
- hoverState.object = nullptr;
- }
- if (hoverState.region && hoverState.region->cursorEnabled) {
- hoverState.object = nullptr;
- hoverState.cursorSequence = kCursorSequenceTransition;
- hoverState.promptText.clear();
- return hoverState;
- }
-
- if (Player::supportsMovementBand(state) &&
- mousePos.y >= state.roomMaxZScreenY &&
- mousePos.y <= state.roomMinZScreenY) {
- hoverState.cursorSequence = kCursorSequenceWalk;
- }
-
- return hoverState;
-}
-
RoomHoverState Flow::getRoomHoverState(const SceneState &scene) const {
- return resolveRoomHoverState(_engine, scene.state, scene.sceneObjects,
+ return Input::resolveRoomHoverState(_engine, scene.state, scene.sceneObjects,
scene.state.roomNpcs, scene.sceneRegions, _mousePos, _menuTextConfig, &_dialogue);
}
@@ -584,7 +335,7 @@ static bool findRoomObjectProbePoint(HarvesterEngine &engine, const Common::Arra
Common::Point(bounds.right - 1, bounds.bottom - 1)
};
for (const Common::Point &candidate : corners) {
- const ObjectRecord *hit = findRoomObjectAtPoint(engine, sceneObjects, candidate);
+ const ObjectRecord *hit = Input::findRoomObjectAtPoint(engine, sceneObjects, candidate);
if (hit && hit->objectName.equalsIgnoreCase(object.objectName)) {
probePoint = candidate;
return true;
@@ -596,7 +347,7 @@ static bool findRoomObjectProbePoint(HarvesterEngine &engine, const Common::Arra
for (int y = bounds.top; y < bounds.bottom; y += yStep) {
for (int x = bounds.left; x < bounds.right; x += xStep) {
const Common::Point candidate(x, y);
- const ObjectRecord *hit = findRoomObjectAtPoint(engine, sceneObjects, candidate);
+ const ObjectRecord *hit = Input::findRoomObjectAtPoint(engine, sceneObjects, candidate);
if (hit && hit->objectName.equalsIgnoreCase(object.objectName)) {
probePoint = candidate;
return true;
@@ -646,14 +397,14 @@ void Flow::logStartupRoomProbe(const SceneState &scene, const Common::String &en
if (!findRoomObjectProbePoint(_engine, scene.sceneObjects, object, probePoint))
continue;
- const ObjectRecord *hoveredObject = findRoomObjectAtPoint(_engine, scene.sceneObjects, probePoint);
+ const ObjectRecord *hoveredObject = Input::findRoomObjectAtPoint(_engine, scene.sceneObjects, probePoint);
if (!hoveredObject)
continue;
_mousePos = probePoint;
const Common::String objectLabel = script->resolveObjectLabel(*hoveredObject);
ResolvedText inspectText;
- const RoomHoverState hoverState = resolveRoomHoverState(
+ const RoomHoverState hoverState = Input::resolveRoomHoverState(
_engine, scene.state, scene.sceneObjects, scene.state.roomNpcs, scene.sceneRegions,
probePoint, _menuTextConfig);
const bool hasInteraction = script->hasObjectInteraction(*hoveredObject);
@@ -670,7 +421,7 @@ void Flow::logStartupRoomProbe(const SceneState &scene, const Common::String &en
bool foundFloorProbe = false;
for (int y = scene.state.roomMaxZScreenY; y <= scene.state.roomMinZScreenY && !foundFloorProbe; y += 12) {
for (int x = 48; x < 592; x += 16) {
- const RoomHoverState candidateHover = resolveRoomHoverState(
+ const RoomHoverState candidateHover = Input::resolveRoomHoverState(
_engine, scene.state, scene.sceneObjects, scene.state.roomNpcs, scene.sceneRegions,
Common::Point(x, y), _menuTextConfig);
if (candidateHover.cursorSequence == kCursorSequenceWalk) {
@@ -682,7 +433,7 @@ void Flow::logStartupRoomProbe(const SceneState &scene, const Common::String &en
}
const RoomHoverState floorHover = foundFloorProbe
- ? resolveRoomHoverState(_engine, scene.state, scene.sceneObjects, scene.state.roomNpcs,
+ ? Input::resolveRoomHoverState(_engine, scene.state, scene.sceneObjects, scene.state.roomNpcs,
scene.sceneRegions, floorProbe, _menuTextConfig)
: RoomHoverState();
debugC(1, kDebugRoom,
diff --git a/engines/harvester/input.cpp b/engines/harvester/input.cpp
index dee80e80534..4a2122367f9 100644
--- a/engines/harvester/input.cpp
+++ b/engines/harvester/input.cpp
@@ -26,6 +26,7 @@
#include "harvester/art.h"
#include "harvester/cheats.h"
#include "harvester/detection.h"
+#include "harvester/dialogue.h"
#include "harvester/flow.h"
#include "harvester/harvester.h"
#include "harvester/inventory.h"
@@ -38,6 +39,14 @@
namespace Harvester {
+static const int kCursorSequenceWalk = 0;
+static const int kCursorSequenceExamine = 1;
+static const int kCursorSequenceTalk = 2;
+static const int kCursorSequenceOperate = 4;
+static const int kCursorSequencePickup = 5;
+static const int kCursorSequenceTransition = 6;
+static const int kCursorSequenceNeutral = 7;
+
static const uint32 kRoomExitFastClickWindowTicks = 20;
static const int kNativeInventoryDragCloseLeft = 0x45;
static const int kNativeInventoryDragCloseTop = 0x4b;
@@ -76,6 +85,250 @@ static void debugLogInventoryClick(const char *buttonLabel, const Common::Point
InventorySystem::isStatusObject(inventoryHover->object));
}
+static bool canTalkToRoomNpc(HarvesterEngine &engine, const NpcRecord &npc,
+ const DialogueSystem *dialogue) {
+ Script *script = engine.getScript();
+ if (!script || !script->isNamedNpcDeathTypeClear(npc.npcName))
+ return false;
+
+ return dialogue && dialogue->hasRoomNpcHandler(npc.npcName);
+}
+
+const ObjectRecord *Input::findRoomObjectAtPoint(HarvesterEngine &engine,
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Point &point) {
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ if (!entityManager)
+ return nullptr;
+
+ const Entity *topEntity = nullptr;
+ const ObjectRecord *topObject = nullptr;
+ int topDrawIndex = -1;
+ for (const ObjectRecord &object : sceneObjects) {
+ if (object.objectName.empty())
+ continue;
+
+ const Entity *entity = entityManager->findSceneEntityByName(object.objectName);
+ if (!entity || !entity->hitTest(point))
+ continue;
+ if (entity->getClassId() == kEntityClassBackground ||
+ entity->getClassId() == kEntityClassPlayer ||
+ entity->getClassId() == kEntityClassRectHotspot19) {
+ continue;
+ }
+ const int drawIndex = entityManager->findSceneEntityDrawIndexByName(entity->getName());
+ if (drawIndex < 0)
+ continue;
+ const bool objectVisible = object.visible && object.runtimeVisible;
+ const bool topObjectVisible = topObject && topObject->visible && topObject->runtimeVisible;
+ if (!topEntity ||
+ (objectVisible && !topObjectVisible) ||
+ (objectVisible == topObjectVisible && drawIndex > topDrawIndex)) {
+ topEntity = entity;
+ topObject = &object;
+ topDrawIndex = drawIndex;
+ }
+ }
+ if (!topEntity)
+ return nullptr;
+
+ return topObject;
+}
+
+static const RegionRecord *findRoomRegionAtPoint(HarvesterEngine &engine,
+ const Common::Array<RegionRecord> &sceneRegions, const Common::Point &point) {
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ if (!entityManager)
+ return nullptr;
+
+ const Entity *topEntity = nullptr;
+ int topDrawIndex = -1;
+ for (const RegionRecord ®ion : sceneRegions) {
+ const Entity *entity = entityManager->findSceneEntityByName(region.regionName);
+ if (!entity || !entity->hitTest(point))
+ continue;
+ if (entity->getClassId() != kEntityClassRectHotspot19)
+ continue;
+ const int drawIndex = entityManager->findSceneEntityDrawIndexByName(entity->getName());
+ if (drawIndex < 0)
+ continue;
+ if (!topEntity || drawIndex > topDrawIndex) {
+ topEntity = entity;
+ topDrawIndex = drawIndex;
+ }
+ }
+ if (!topEntity)
+ return nullptr;
+
+ return SceneEntities::findSceneRegionByName(sceneRegions, topEntity->getName());
+}
+
+static const Entity *findRoomPlayerAtPoint(HarvesterEngine &engine, const Common::Point &point) {
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ if (!entityManager)
+ return nullptr;
+
+ const Entity *entity = entityManager->findTopSceneEntityAt(point);
+ if (!entity || entity->getClassId() != kEntityClassPlayer)
+ return nullptr;
+
+ return entity;
+}
+
+static const NpcRecord *findRoomNpcAtPoint(HarvesterEngine &engine,
+ const Common::Array<NpcRecord> &sceneNpcs, const Common::Point &point,
+ const DialogueSystem *dialogue) {
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ if (!entityManager)
+ return nullptr;
+
+ const Entity *entity = entityManager->findTopSceneEntityAt(point);
+ if (!entity || entity->getClassId() != kEntityClassNpc)
+ return nullptr;
+
+ const NpcRecord *npc = SceneEntities::findSceneNpcByName(sceneNpcs, entity->getName());
+ if (!npc || !canTalkToRoomNpc(engine, *npc, dialogue))
+ return nullptr;
+
+ return npc;
+}
+
+static bool suppressesInitialObjectInspectGate(const ObjectRecord &object) {
+ // Native HARVEST.SCR uses ident key X as a no-text sentinel.
+ return object.identTextKey.equalsIgnoreCase("X");
+}
+
+static bool usesBareOperatePrompt(const ObjectRecord &object) {
+ return object.objectName.equalsIgnoreCase("HAPPLY_HS") ||
+ object.objectName.equalsIgnoreCase("KILL_STEPH_HS");
+}
+
+static bool unlocksRoomObjectInteractionAfterInitialExamine(const ObjectRecord &object,
+ Script &script) {
+ if (suppressesInitialObjectInspectGate(object))
+ return false;
+
+ return object.operatable || script.isPickupObject(object);
+}
+
+static int resolveRoomObjectCursorSequence(const ObjectRecord &object, Script &script) {
+ if (object.objectName.equalsIgnoreCase("EXIT_BM") || object.objectName.equalsIgnoreCase("EXIT_HS"))
+ return kCursorSequenceTransition;
+
+ ResolvedText inspectText;
+ const bool pickupObject = script.isPickupObject(object);
+ const bool pickupBlocked = pickupObject && script.isPickupBlockedByAction(object);
+ if (!object.identShown && unlocksRoomObjectInteractionAfterInitialExamine(object, script))
+ return kCursorSequenceExamine;
+ if (pickupObject && !pickupBlocked)
+ return kCursorSequencePickup;
+ if (pickupBlocked)
+ return kCursorSequenceExamine;
+ if (object.operatable)
+ return kCursorSequenceOperate;
+ if (script.resolveObjectInspectText(object, inspectText))
+ return kCursorSequenceExamine;
+
+ if (script.hasObjectInteraction(object))
+ return kCursorSequenceExamine;
+
+ return kCursorSequenceNeutral;
+}
+
+static Common::String buildRoomObjectPrompt(const ObjectRecord &object, Script &script,
+ int cursorSequence, const MenuTextConfig &menuTextConfig) {
+ // Native room prompts come from explicit interaction metadata. Neutral scene sprites
+ // should not surface synthetic "Examine <object id>" prompts or steal hover/click focus.
+ if (cursorSequence == kCursorSequenceNeutral)
+ return Common::String();
+
+ const Common::String label = script.resolveObjectLabel(object);
+ if (label.empty())
+ return Common::String();
+
+ if (cursorSequence == kCursorSequenceOperate) {
+ if (usesBareOperatePrompt(object))
+ return label;
+ return Common::String::format("%s %s", menuTextConfig.operateVerb.c_str(), label.c_str());
+ }
+ if (cursorSequence == kCursorSequencePickup)
+ return Common::String::format("%s %s", menuTextConfig.pickUpVerb.c_str(), label.c_str());
+ if (cursorSequence == kCursorSequenceTalk)
+ return Common::String::format("%s %s", menuTextConfig.talkToVerb.c_str(), label.c_str());
+ if (cursorSequence == kCursorSequenceTransition)
+ return Common::String::format("Go to %s", label.c_str());
+
+ return Common::String::format("%s %s", menuTextConfig.examineTheVerb.c_str(), label.c_str());
+}
+
+static Common::String buildRoomNpcPrompt(const NpcRecord &npc,
+ const MenuTextConfig &menuTextConfig) {
+ Common::String label = !npc.entityInitArg.empty() ? npc.entityInitArg : npc.npcName;
+ for (uint i = 0; i < label.size(); ++i) {
+ if (label[i] == '_')
+ label.setChar(' ', i);
+ }
+
+ if (label.empty())
+ return Common::String();
+ return Common::String::format("%s %s", menuTextConfig.talkToVerb.c_str(), label.c_str());
+}
+
+RoomHoverState Input::resolveRoomHoverState(HarvesterEngine &engine, const RoomSetupState &state,
+ const Common::Array<ObjectRecord> &sceneObjects,
+ const Common::Array<NpcRecord> &sceneNpcs,
+ const Common::Array<RegionRecord> &sceneRegions, const Common::Point &mousePos,
+ const MenuTextConfig &menuTextConfig, const DialogueSystem *dialogue) {
+ RoomHoverState hoverState;
+ EntityManager *entityManager = engine.getRuntimeEntities();
+ if (const Entity *playerEntity = findRoomPlayerAtPoint(engine, mousePos)) {
+ hoverState.playerEntity = playerEntity;
+ hoverState.cursorSequence = kCursorSequenceExamine;
+ return hoverState;
+ }
+ if (const NpcRecord *npc = findRoomNpcAtPoint(engine, sceneNpcs, mousePos, dialogue)) {
+ hoverState.npc = npc;
+ hoverState.cursorSequence = kCursorSequenceTalk;
+ hoverState.promptText = buildRoomNpcPrompt(*npc, menuTextConfig);
+ return hoverState;
+ }
+
+ Script *script = engine.getScript();
+ if (!script)
+ return hoverState;
+ hoverState.object = findRoomObjectAtPoint(engine, sceneObjects, mousePos);
+ hoverState.region = findRoomRegionAtPoint(engine, sceneRegions, mousePos);
+ if (entityManager && hoverState.object && hoverState.region) {
+ const int objectDrawIndex =
+ entityManager->findSceneEntityDrawIndexByName(hoverState.object->objectName);
+ const int regionDrawIndex =
+ entityManager->findSceneEntityDrawIndexByName(hoverState.region->regionName);
+ if (regionDrawIndex >= 0 && objectDrawIndex >= 0 && regionDrawIndex > objectDrawIndex)
+ hoverState.object = nullptr;
+ }
+ if (hoverState.object) {
+ hoverState.cursorSequence = resolveRoomObjectCursorSequence(*hoverState.object, *script);
+ hoverState.promptText = buildRoomObjectPrompt(
+ *hoverState.object, *script, hoverState.cursorSequence, menuTextConfig);
+ if (hoverState.cursorSequence != kCursorSequenceNeutral || !hoverState.promptText.empty())
+ return hoverState;
+ hoverState.object = nullptr;
+ }
+ if (hoverState.region && hoverState.region->cursorEnabled) {
+ hoverState.object = nullptr;
+ hoverState.cursorSequence = kCursorSequenceTransition;
+ hoverState.promptText.clear();
+ return hoverState;
+ }
+
+ if (Player::supportsMovementBand(state) &&
+ mousePos.y >= state.roomMaxZScreenY &&
+ mousePos.y <= state.roomMinZScreenY) {
+ hoverState.cursorSequence = kCursorSequenceWalk;
+ }
+
+ return hoverState;
+}
+
Input::Input(HarvesterEngine &engine, Flow &flow, Scene &session, SceneState &scene,
InventorySystem &inventory, CheatSystem &cheats,
ItemInteractions &roomItems, Interaction &interactionProcessor,
diff --git a/engines/harvester/input.h b/engines/harvester/input.h
index f4eeddfcd52..224722a90d6 100644
--- a/engines/harvester/input.h
+++ b/engines/harvester/input.h
@@ -22,22 +22,30 @@
#ifndef HARVESTER_INPUT_H
#define HARVESTER_INPUT_H
+#include "common/array.h"
#include "common/error.h"
#include "common/events.h"
+#include "common/rect.h"
namespace Harvester {
class Art;
class CheatSystem;
+class DialogueSystem;
class Flow;
class HarvesterEngine;
class InventorySystem;
class Interaction;
class ItemInteractions;
class Scene;
+struct MenuTextConfig;
+struct NpcRecord;
struct ObjectRecord;
+struct RegionRecord;
struct ResolvedText;
+struct RoomHoverState;
struct RoomPresentationState;
+struct RoomSetupState;
struct SceneState;
struct InputState {
@@ -73,6 +81,15 @@ public:
InputResult handleEvent(const Common::Event &event, bool &needsRedraw);
+ static const ObjectRecord *findRoomObjectAtPoint(HarvesterEngine &engine,
+ const Common::Array<ObjectRecord> &sceneObjects, const Common::Point &point);
+ static RoomHoverState resolveRoomHoverState(HarvesterEngine &engine, const RoomSetupState &state,
+ const Common::Array<ObjectRecord> &sceneObjects,
+ const Common::Array<NpcRecord> &npcs,
+ const Common::Array<RegionRecord> ®ions,
+ const Common::Point &mousePos, const MenuTextConfig &menuTextConfig,
+ const DialogueSystem *dialogue = nullptr);
+
private:
void handleMouseMove(bool &needsRedraw);
InputResult handleRightButtonDown(bool &needsRedraw);
diff --git a/engines/harvester/room_support.h b/engines/harvester/room_support.h
index 35f6b22dddd..755d5895b66 100644
--- a/engines/harvester/room_support.h
+++ b/engines/harvester/room_support.h
@@ -71,16 +71,8 @@ void logScenePaletteSummary(const char *label, const SceneState &scene, float br
bool captureScreenBackdrop(const Graphics::Screen &screen, IndexedBitmap &bitmap);
bool shouldDisplaySceneAnimation(const AnimRecord &anim);
bool shouldRunStartupRoomProbe();
-bool unlocksRoomObjectInteractionAfterInitialExamine(const ObjectRecord &object,
- Script &script);
bool doesPlayerFacingMatchRegion(int playerFacing, const RegionRecord ®ion);
bool doesPlayerOverlapRegion(const Entity &playerEntity, const RegionRecord ®ion);
-RoomHoverState resolveRoomHoverState(HarvesterEngine &engine, const RoomSetupState &state,
- const Common::Array<ObjectRecord> &sceneObjects,
- const Common::Array<NpcRecord> &npcs,
- const Common::Array<RegionRecord> ®ions,
- const Common::Point &mousePos, const MenuTextConfig &menuTextConfig,
- const DialogueSystem *dialogue = nullptr);
} // End of namespace Harvester
Commit: d092cf2688ceb23ae0bcc091b780e802a56c8384
https://github.com/scummvm/scummvm/commit/d092cf2688ceb23ae0bcc091b780e802a56c8384
Author: Alex Bevilacqua (alex at alexbevi.com)
Date: 2026-10-17T08:38:08-04:00
Commit Message:
HARVESTER: Fix cursor freezing after idle animations
Assisted-by: Codex:gpt-6.1-sol
Changed paths:
engines/harvester/flow.cpp
diff --git a/engines/harvester/flow.cpp b/engines/harvester/flow.cpp
index 99a8e1073a7..cdca29d8b79 100644
--- a/engines/harvester/flow.cpp
+++ b/engines/harvester/flow.cpp
@@ -1552,7 +1552,9 @@ bool Flow::tickRuntimeEntities() {
EntityManager *entityManager = _engine.getRuntimeEntities();
if (!entityManager)
return false;
- return entityManager->tickSceneEntities() || entityManager->syncCursorEntityPosition(_mousePos);
+ const bool sceneChanged = entityManager->tickSceneEntities();
+ const bool cursorChanged = entityManager->syncCursorEntityPosition(_mousePos);
+ return sceneChanged || cursorChanged;
}
bool Flow::handleSystemEvent(const Common::Event &event, Common::Error &result) {
More information about the Scummvm-git-logs
mailing list