[Scummvm-git-logs] scummvm master -> 4b274641fb88d0873ef36a3dcc844461c68f5d46
fracturehill
noreply at scummvm.org
Sun Feb 18 21:32:16 UTC 2024
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
18eea6d464 NANCY: Add support for nancy9 RippedLetterPuzzle
f89967c979 NANCY: Implement NewPhone
4b274641fb DEVTOOLS: Fix typos in nancy.dat
Commit: 18eea6d464708fbe25ab7e62059c4ddae83a62c9
https://github.com/scummvm/scummvm/commit/18eea6d464708fbe25ab7e62059c4ddae83a62c9
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2024-02-18T22:31:13+01:00
Commit Message:
NANCY: Add support for nancy9 RippedLetterPuzzle
In nancy9 this record got an upgrade allowing for an
extra solution, as well as duplicated elements.
Changed paths:
engines/nancy/action/puzzle/rippedletterpuzzle.cpp
engines/nancy/action/puzzle/rippedletterpuzzle.h
engines/nancy/util.cpp
diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
index 1560ed31318..709079357a3 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
@@ -76,15 +76,18 @@ void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
height = stream.readByte();
}
+ // All the checks for whether width is greater than maxWidth are
+ // to account for nancy9 scene 2428, where the dimensions are 15x1
+
for (uint i = 0; i < height; ++i) {
readRectArray(stream, _srcRects, width, maxWidth);
}
- stream.skip((maxHeight - height) * maxWidth * 16);
+ stream.skip((maxWidth >= width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * 16);
for (uint i = 0; i < height; ++i) {
readRectArray(stream, _destRects, width, maxWidth);
}
- stream.skip((maxHeight - height) * maxWidth * 16);
+ stream.skip((maxWidth >= width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * 16);
readRect(stream, _rotateHotspot);
readRect(stream, _takeHotspot);
@@ -94,41 +97,79 @@ void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
_rotationType = (RotationType)stream.readUint16LE();
}
+ uint elemSize = g_nancy->getGameType() <= kGameTypeNancy8 ? 1 : 2;
+
_initOrder.resize(width * height);
for (uint i = 0; i < height; ++i) {
for (uint j = 0; j < width; ++j) {
- _initOrder[i * width + j] = stream.readByte();
+ _initOrder[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
}
- stream.skip((maxWidth - width));
+ stream.skip(maxWidth > width ? (maxWidth - width) * elemSize : 0);
}
- stream.skip((maxHeight - height) * maxWidth);
+ stream.skip((maxWidth > width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * elemSize);
_initRotations.resize(width * height);
for (uint i = 0; i < height; ++i) {
for (uint j = 0; j < width; ++j) {
- _initRotations[i * width + j] = stream.readByte();
+ _initRotations[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
+ }
+ stream.skip(maxWidth > width ? (maxWidth - width) * elemSize : 0);
+ }
+ stream.skip((maxWidth > width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * elemSize);
+
+ if (g_nancy->getGameType() >= kGameTypeNancy9) {
+ uint16 numDoubledElements = stream.readUint16LE();
+ _doubles.resize(numDoubledElements);
+ uint i = 0;
+ for (uint j = 0; j < 20; ++j) {
+ int16 id = stream.readSint16LE();
+ if (id == -1) {
+ ++i;
+ } else {
+ _doubles[i].push_back(id);
+ }
}
- stream.skip((maxWidth - width));
}
- stream.skip((maxHeight - height) * maxWidth);
_solveOrder.resize(width * height);
for (uint i = 0; i < height; ++i) {
for (uint j = 0; j < width; ++j) {
- _solveOrder[i * width + j] = stream.readByte();
+ _solveOrder[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
}
- stream.skip((maxWidth - width));
+ stream.skip(maxWidth > width ? (maxWidth - width) * elemSize : 0);
}
- stream.skip((maxHeight - height) * maxWidth);
+ stream.skip((maxWidth > width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * elemSize);
_solveRotations.resize(width * height);
for (uint i = 0; i < height; ++i) {
for (uint j = 0; j < width; ++j) {
- _solveRotations[i * width + j] = stream.readByte();
+ _solveRotations[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
+ }
+ stream.skip(maxWidth > width ? (maxWidth - width) * elemSize : 0);
+ }
+ stream.skip((maxWidth > width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * elemSize);
+
+ if (g_nancy->getGameType() >= kGameTypeNancy9) {
+ _useAltSolution = stream.readByte();
+
+ _solveOrderAlt.resize(width * height);
+ for (uint i = 0; i < height; ++i) {
+ for (uint j = 0; j < width; ++j) {
+ _solveOrderAlt[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
+ }
+ stream.skip(maxWidth > width ? (maxWidth - width) * elemSize : 0);
}
- stream.skip((maxWidth - width));
+ stream.skip((maxWidth > width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * elemSize);
+
+ _solveRotationsAlt.resize(width * height);
+ for (uint i = 0; i < height; ++i) {
+ for (uint j = 0; j < width; ++j) {
+ _solveRotationsAlt[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
+ }
+ stream.skip(maxWidth > width ? (maxWidth - width) * elemSize : 0);
+ }
+ stream.skip((maxWidth > width ? (maxHeight - height) * maxWidth : maxWidth * maxHeight - width * height) * elemSize);
}
- stream.skip((maxHeight - height) * maxWidth);
if (g_nancy->getGameType() >= kGameTypeNancy7) {
_useCustomPickUpTile = stream.readByte();
@@ -144,6 +185,10 @@ void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
_exitScene.readData(stream);
readRect(stream, _exitHotspot);
+
+ if (g_nancy->getGameType() >= kGameTypeNancy9) {
+ _customCursorID = stream.readSint16LE();
+ }
}
void RippedLetterPuzzle::execute() {
@@ -174,8 +219,14 @@ void RippedLetterPuzzle::execute() {
switch (_solveState) {
case kNotSolved :
for (uint i = 0; i < _puzzleState->order.size(); ++i) {
- if (_puzzleState->order[i] != _solveOrder[i] || _puzzleState->rotations[i] != _solveRotations[i]) {
- return;
+ if (_puzzleState->rotations[i] != _solveRotations[i] || !checkOrder(false)) {
+ if (_useAltSolution) {
+ if (!checkOrder(true)) {
+ return;
+ }
+ } else {
+ return;
+ }
}
}
@@ -199,6 +250,10 @@ void RippedLetterPuzzle::execute() {
_exitScene.execute();
break;
case kWaitForSound:
+ if (_solveExitScene._sceneChange.sceneID == NancySceneState.getSceneInfo().sceneID) {
+ // nancy9 scene 2484 is auto-solved for you, but has a valid scene change back to itself
+ return;
+ }
_solveExitScene.execute();
_puzzleState->playerHasTriedPuzzle = false;
break;
@@ -212,7 +267,7 @@ void RippedLetterPuzzle::execute() {
}
void RippedLetterPuzzle::handleInput(NancyInput &input) {
- if (_state != kRun && _solveState != kNotSolved) {
+ if (_state == kBegin) {
return;
}
@@ -325,7 +380,7 @@ void RippedLetterPuzzle::handleInput(NancyInput &input) {
if (_pickedUpPieceID == -1) {
// No piece picked up, check the exit hotspot
if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
- g_nancy->_cursor->setCursorType(g_nancy->_cursor->_puzzleExitCursor);
+ g_nancy->_cursor->setCursorType(_customCursorID != -1 ? (CursorManager::CursorType)_customCursorID : g_nancy->_cursor->_puzzleExitCursor);
if (input.input & NancyInput::kLeftMouseButtonUp) {
// Player has clicked, exit
@@ -351,5 +406,50 @@ void RippedLetterPuzzle::drawPiece(const uint pos, const byte rotation, const in
GraphicsManager::rotateBlit(srcSurf, destSurf, rotation);
}
+bool RippedLetterPuzzle::checkOrder(bool useAlt) {
+ auto ¤t = _puzzleState->order;
+ auto &correct = useAlt ? _solveOrderAlt : _solveOrder;
+
+ if (!_doubles.size()) {
+ return current == correct;
+ }
+
+ for (uint i = 0; i < current.size(); ++i) {
+ bool foundCorrect = false;
+ bool isDoubled = false;
+ for (auto &d : _doubles) {
+ for (byte e : d) {
+ if (current[i] == e) {
+ isDoubled = true;
+ break;
+ }
+ }
+
+ if (isDoubled) {
+ for (byte e : d) {
+ if (correct[i] == e) {
+ foundCorrect = true;
+ break;
+ }
+ }
+
+ if (!foundCorrect) {
+ return false;
+ }
+
+ break;
+ }
+ }
+
+ if (!isDoubled) {
+ if (current[i] != correct[i]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
} // End of namespace Action
} // End of namespace Nancy
diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.h b/engines/nancy/action/puzzle/rippedletterpuzzle.h
index 09fe7c942a5..4ea8223d8da 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.h
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.h
@@ -59,6 +59,10 @@ public:
Common::Array<byte> _initRotations;
Common::Array<int8> _solveOrder;
Common::Array<byte> _solveRotations;
+ Common::Array<int8> _solveOrderAlt;
+ Common::Array<byte> _solveRotationsAlt;
+ Common::Array<Common::Array<byte>> _doubles;
+ bool _useAltSolution = false;
bool _useCustomPickUpTile = false;
Common::Rect _customPickUpTileSrc;
@@ -73,6 +77,8 @@ public:
SceneChangeWithFlag _exitScene;
Common::Rect _exitHotspot;
+ int16 _customCursorID = -1;
+
Misc::MouseFollowObject _pickedUpPiece;
int8 _pickedUpPieceID = -1;
byte _pickedUpPieceRot = 0;
@@ -86,6 +92,7 @@ protected:
bool isViewportRelative() const override { return true; }
void drawPiece(const uint pos, const byte rotation, const int pieceID = -1);
+ bool checkOrder(bool useAlt);
};
} // End of namespace Action
diff --git a/engines/nancy/util.cpp b/engines/nancy/util.cpp
index 819f41d3ab4..78d22d2b8ef 100644
--- a/engines/nancy/util.cpp
+++ b/engines/nancy/util.cpp
@@ -65,7 +65,7 @@ void readRectArray(Common::SeekableReadStream &stream, Common::Array<Common::Rec
totalNum = num;
}
- stream.skip((totalNum - num) * 16);
+ stream.skip(totalNum > num ? (totalNum - num) * 16 : 0);
}
void readRectArray(Common::Serializer &stream, Common::Array<Common::Rect> &inArray, uint num, uint totalNum, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
@@ -91,7 +91,7 @@ void readRectArray(Common::Serializer &stream, Common::Array<Common::Rect> &inAr
totalNum = num;
}
- stream.skip((totalNum - num) * 16);
+ stream.skip(totalNum > num ? (totalNum - num) * 16 : 0);
}
}
@@ -136,7 +136,7 @@ void readRectArray16(Common::SeekableReadStream &stream, Common::Array<Common::R
totalNum = num;
}
- stream.skip((totalNum - num) * 8);
+ stream.skip(totalNum > num ? (totalNum - num) * 8 : 0);
}
void readRectArray16(Common::Serializer &stream, Common::Array<Common::Rect> &inArray, uint num, uint totalNum, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
@@ -162,7 +162,7 @@ void readRectArray16(Common::Serializer &stream, Common::Array<Common::Rect> &in
totalNum = num;
}
- stream.skip((totalNum - num) * 8);
+ stream.skip(totalNum > num ? (totalNum - num) * 8 : 0);
}
}
Commit: f89967c979ec5d977a45926f01fa5267d06c3bdb
https://github.com/scummvm/scummvm/commit/f89967c979ec5d977a45926f01fa5267d06c3bdb
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2024-02-18T22:31:13+01:00
Commit Message:
NANCY: Implement NewPhone
Added support for the new Telephone AR type, which
adds a cellphone display with a phone number directory,
a dial button, and conditional phone numbers.
Changed paths:
engines/nancy/action/arfactory.cpp
engines/nancy/action/puzzle/telephone.cpp
engines/nancy/action/puzzle/telephone.h
engines/nancy/resource.cpp
diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index 6be4f83cd8f..600a419e30f 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -253,7 +253,7 @@ ActionRecord *ActionManager::createActionRecord(uint16 type, Common::SeekableRea
case 115:
return new LeverPuzzle();
case 116:
- return new Telephone();
+ return new Telephone(false);
case 117:
return new SliderPuzzle();
case 118:
@@ -360,6 +360,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type, Common::SeekableRea
return new OrderingPuzzle(OrderingPuzzle::kKeypadTerse);
case 225:
return new SpigotPuzzle();
+ case 230:
+ return new Telephone(true);
default:
return nullptr;
}
diff --git a/engines/nancy/action/puzzle/telephone.cpp b/engines/nancy/action/puzzle/telephone.cpp
index 0e4d05c9660..57e1a7bbd94 100644
--- a/engines/nancy/action/puzzle/telephone.cpp
+++ b/engines/nancy/action/puzzle/telephone.cpp
@@ -25,6 +25,7 @@
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/util.h"
+#include "engines/nancy/font.h"
#include "engines/nancy/action/puzzle/telephone.h"
@@ -34,41 +35,86 @@ namespace Nancy {
namespace Action {
void Telephone::init() {
- _drawSurface.create(_screenPosition.width(), _screenPosition.height(), g_nancy->_graphics->getInputPixelFormat());
+ Common::Rect screenBounds = NancySceneState.getViewport().getBounds();
+ _drawSurface.create(screenBounds.width(), screenBounds.height(), g_nancy->_graphics->getInputPixelFormat());
_drawSurface.clear(g_nancy->_graphics->getTransColor());
-
setTransparent(true);
+ setVisible(true);
+ moveTo(screenBounds);
g_nancy->_resource->loadImage(_imageName, _image);
+ g_nancy->_resource->loadImage(_displayAnimName, _animImage);
+
+ if (_isNewPhone) {
+ _font = g_nancy->_graphics->getFont(_displayFont);
+ }
}
void Telephone::readData(Common::SeekableReadStream &stream) {
readFilename(stream, _imageName);
- readRectArray(stream, _srcRects, 12);
- readRectArray(stream, _destRects, 12);
+ uint16 numButtons = 12;
+ uint16 maxNumButtons = _isNewPhone ? 20 : 12;
+
+ if (_isNewPhone) {
+ _hasDisplay = stream.readByte();
+ _displayFont = stream.readUint16LE();
+ readFilename(stream, _displayAnimName);
+ _displayAnimFrameTime = stream.readUint32LE();
+ uint16 numFrames = stream.readUint16LE();
+ readRectArray(stream, _displaySrcs, numFrames, 10);
+ readRect(stream, _displayDest);
+ _dialAutomatically = stream.readByte();
+
+ numButtons = stream.readUint16LE();
+ }
+
+ readRectArray(stream, _srcRects, numButtons, maxNumButtons);
+ readRectArray(stream, _destRects, numButtons, maxNumButtons);
- _screenPosition = _destRects[0];
- for (uint i = 0; i < 12; ++i) {
- _screenPosition.extend(_destRects[i]);
+ if (_isNewPhone) {
+ readRect(stream, _dirHighlightSrc);
+ readRect(stream, _dialHighlightSrc);
+
+ _upDirButtonID = stream.readUint16LE();
+ _downDirButtonID = stream.readUint16LE();
+ _dialButtonID = stream.readUint16LE();
+ _dirButtonID = stream.readUint16LE();
+
+ readRect(stream, _displayDialingSrc);
}
- _genericDialogueSound.readNormal(stream);
- _genericButtonSound.readNormal(stream);
- _ringSound.readNormal(stream);
- _dialToneSound.readNormal(stream);
- _dialAgainSound.readNormal(stream);
- _hangUpSound.readNormal(stream);
+ if (!_isNewPhone) {
+ _genericDialogueSound.readNormal(stream);
+ _genericButtonSound.readNormal(stream);
+ _ringSound.readNormal(stream);
+ _dialToneSound.readNormal(stream);
+ _dialAgainSound.readNormal(stream);
+ _hangUpSound.readNormal(stream);
+ } else {
+ _ringSound.readNormal(stream);
+ _dialToneSound.readNormal(stream);
+ _preCallSound.readNormal(stream);
+ _hangUpSound.readNormal(stream);
+ _genericButtonSound.readNormal(stream);
+ }
- readFilenameArray(stream, _buttonSoundNames, 12);
+ readFilenameArray(stream, _buttonSoundNames, numButtons);
+ stream.skip(33 * (maxNumButtons - numButtons));
char textBuf[200];
- stream.read(textBuf, 200);
- textBuf[199] = '\0';
- _addressBookString = textBuf;
+ if (!_isNewPhone) {
+ stream.read(textBuf, 200);
+ textBuf[199] = '\0';
+ _addressBookString = textBuf;
+ } else {
+ _dialAgainSound.readNormal(stream);
+ }
+
stream.read(textBuf, 200);
textBuf[199] = '\0';
_dialAgainString = textBuf;
+
_reloadScene.readData(stream);
stream.skip(1);
_exitScene.readData(stream);
@@ -81,15 +127,24 @@ void Telephone::readData(Common::SeekableReadStream &stream) {
for (uint i = 0; i < numCalls; ++i) {
PhoneCall &call = _calls[i];
+ if (_isNewPhone) {
+ call.eventFlagCondition = stream.readSint16LE();
+ }
+
call.phoneNumber.resize(11);
for (uint j = 0; j < 11; ++j) {
call.phoneNumber[j] = stream.readByte();
}
- readFilename(stream, call.soundName);
- stream.read(textBuf, 200);
- textBuf[199] = '\0';
- call.text = textBuf;
+ if (!_isNewPhone) {
+ readFilename(stream, call.soundName);
+ stream.read(textBuf, 200);
+ textBuf[199] = '\0';
+ call.text = textBuf;
+ } else {
+ readRect(stream, call.displaySrc);
+ }
+
call.sceneChange.readData(stream);
stream.skip(1);
}
@@ -109,11 +164,36 @@ void Telephone::execute() {
case kRun:
switch (_callState) {
case kWaiting:
+ if (_isNewPhone && !_animIsStopped) {
+ if (g_nancy->getTotalPlayTime() > _displayAnimEnd) {
+ if (_displayAnimEnd == 0) {
+ _displayAnimEnd = g_nancy->getTotalPlayTime() + _displayAnimFrameTime;
+ } else {
+ _displayAnimEnd += _displayAnimFrameTime;
+ }
+
+ _drawSurface.blitFrom(_animImage, _displaySrcs[_displayAnimFrame], _displayDest);
+ _needsRedraw = true;
+ ++_displayAnimFrame;
+
+ if (_displayAnimFrame >= _displaySrcs.size()) {
+ _displayAnimFrame = 0;
+ }
+ }
+ }
+
if (_checkNumbers) {
// Pressed a new button, check all numbers for match
// We do this before going to the ringing state to support nancy4's voice mail system,
// where call numbers can be 1 digit long
for (uint i = 0; i < _calls.size(); ++i) {
+ // Do not evaluate phone calls whose condition isn't met
+ if (_calls[i].eventFlagCondition != kEvNoEvent) {
+ if (NancySceneState.getEventFlag(_calls[i].eventFlagCondition, g_nancy->_false)) {
+ continue;
+ }
+ }
+
bool invalid = false;
for (uint j = 0; j < _calledNumber.size(); ++j) {
@@ -157,16 +237,20 @@ void Telephone::execute() {
}
if (shouldRing) {
- if (_ringSound.name == "NO SOUND") {
- // Will not ring, so skip text
- _callState = kRinging;
- } else {
- NancySceneState.getTextbox().clear();
- NancySceneState.getTextbox().addTextLine(g_nancy->getStaticData().ringingText);
+ if (_ringSound.name != "NO SOUND") {
+ if (_hasDisplay) {
+ _drawSurface.blitFrom(_image, _displayDialingSrc, _displayDest);
+ _needsRedraw = true;
+ } else {
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(g_nancy->getStaticData().ringingText);
+ }
+
g_nancy->_sound->loadSound(_ringSound);
g_nancy->_sound->playSound(_ringSound);
- _callState = kRinging;
}
+
+ _callState = kRinging;
}
_checkNumbers = false;
@@ -176,7 +260,16 @@ void Telephone::execute() {
case kButtonPress:
if (!g_nancy->_sound->isSoundPlaying(_genericButtonSound)) {
g_nancy->_sound->stopSound(_genericButtonSound);
- undrawButton(_buttonLastPushed);
+ _drawSurface.fillRect(_destRects[_buttonLastPushed], g_nancy->_graphics->getTransColor());
+ _needsRedraw = true;
+
+ if (_isShowingDirectory) {
+ _drawSurface.blitFrom(_image, _dirHighlightSrc, _destRects[_dirButtonID]);
+ _drawSurface.blitFrom(_image, _calls[_displayedDirectory].displaySrc, _displayDest);
+ } else if (_dirButtonID != -1) {
+ _drawSurface.fillRect(_destRects[_dirButtonID], _drawSurface.getTransparentColor());
+ }
+
_buttonLastPushed = -1;
_callState = kWaiting;
}
@@ -188,18 +281,39 @@ void Telephone::execute() {
if (_selected != -1) {
// Called a valid number
- NancySceneState.getTextbox().clear();
- NancySceneState.getTextbox().addTextLine(_calls[_selected].text);
-
- _genericDialogueSound.name = _calls[_selected].soundName;
- g_nancy->_sound->loadSound(_genericDialogueSound);
- g_nancy->_sound->playSound(_genericDialogueSound);
- _callState = kCall;
+
+ if (_preCallSound.name == "NO SOUND") {
+ // Old phone, go directly to call
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(_calls[_selected].text);
+
+ _genericDialogueSound.name = _calls[_selected].soundName;
+ g_nancy->_sound->loadSound(_genericDialogueSound);
+ g_nancy->_sound->playSound(_genericDialogueSound);
+ _callState = kCall;
+ } else {
+ // New phone, play a short sound of phone being picked up
+ g_nancy->_sound->loadSound(_preCallSound);
+ g_nancy->_sound->playSound(_preCallSound);
+ _callState = kPreCall;
+ }
} else {
// Called an invalid number
NancySceneState.getTextbox().clear();
NancySceneState.getTextbox().addTextLine(_dialAgainString);
+ if (_hasDisplay) {
+ _drawSurface.fillRect(_displayDest, _drawSurface.getTransparentColor());
+ _needsRedraw = true;
+ }
+
+ if (_dialButtonID != -1) {
+ _drawSurface.fillRect(_destRects[_dialButtonID], _drawSurface.getTransparentColor());
+ _needsRedraw = true;
+ }
+
+ _calledNumber.clear();
+
g_nancy->_sound->loadSound(_dialAgainSound);
g_nancy->_sound->playSound(_dialAgainSound);
_callState = kBadNumber;
@@ -208,6 +322,22 @@ void Telephone::execute() {
return;
}
+ break;
+ case kPreCall:
+ if (!g_nancy->_sound->isSoundPlaying(_preCallSound)) {
+ g_nancy->_sound->stopSound(_preCallSound);
+
+ if (!_calls[_selected].text.empty()) {
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(_calls[_selected].text);
+ }
+
+ _genericDialogueSound.name = _calls[_selected].soundName;
+ g_nancy->_sound->loadSound(_genericDialogueSound);
+ g_nancy->_sound->playSound(_genericDialogueSound);
+ _callState = kCall;
+ }
+
break;
case kBadNumber:
if (!g_nancy->_sound->isSoundPlaying(_dialAgainSound)) {
@@ -260,12 +390,12 @@ void Telephone::execute() {
break;
}
- g_nancy->_sound->stopSound(_hangUpSound);
- g_nancy->_sound->stopSound(_genericDialogueSound);
- g_nancy->_sound->stopSound(_genericButtonSound);
- g_nancy->_sound->stopSound(_dialAgainSound);
- g_nancy->_sound->stopSound(_ringSound);
- g_nancy->_sound->stopSound(_dialToneSound);
+ g_nancy->_sound->stopSound(_hangUpSound);
+ g_nancy->_sound->stopSound(_genericDialogueSound);
+ g_nancy->_sound->stopSound(_genericButtonSound);
+ g_nancy->_sound->stopSound(_dialAgainSound);
+ g_nancy->_sound->stopSound(_ringSound);
+ g_nancy->_sound->stopSound(_dialToneSound);
finishExecution();
}
@@ -274,7 +404,12 @@ void Telephone::execute() {
void Telephone::handleInput(NancyInput &input) {
int buttonNr = -1;
// Cursor gets changed regardless of state
- for (uint i = 0; i < 12; ++i) {
+ for (int i = 0; i < (int)_destRects.size(); ++i) {
+ // Dial button is an exception
+ if (i == _dialButtonID && !_calledNumber.size() && !_isShowingDirectory) {
+ continue;
+ }
+
if (NancySceneState.getViewport().convertViewportToScreen(_destRects[i]).contains(input.mousePos)) {
g_nancy->_cursor->setCursorType(CursorManager::kHotspot);
buttonNr = i;
@@ -309,34 +444,128 @@ void Telephone::handleInput(NancyInput &input) {
g_nancy->_sound->stopSound(_dialToneSound);
}
- _calledNumber.push_back(buttonNr);
+ // Handle non-digit numbers
+ bool directorySwitch = false;
+ bool changeDirectoryEntry = false;
+ int dirEntryDelta = 1;
+ if (_dialButtonID != -1 && buttonNr == _dialButtonID) {
+ _calledNumber = _calls[_displayedDirectory].phoneNumber;
+ while (_calledNumber.back() == 10) {
+ _calledNumber.pop_back();
+ }
+
+ _checkNumbers = true;
+
+ // Dial button doesn't make sound, and doesn't get pressed down
+ _drawSurface.blitFrom(_image, _dialHighlightSrc, _destRects[_dialButtonID]);
+
+ if (_dirButtonID != -1) {
+ _drawSurface.fillRect(_destRects[_dirButtonID], _drawSurface.getTransparentColor());
+ }
+
+ return;
+ } else if (_upDirButtonID != -1 && buttonNr == _upDirButtonID) {
+ if (!_isShowingDirectory) {
+ directorySwitch = true;
+ } else {
+ ++_displayedDirectory;
+ changeDirectoryEntry = true;
+ }
+ } else if (_downDirButtonID != -1 && buttonNr == _downDirButtonID) {
+ if (!_isShowingDirectory) {
+ directorySwitch = true;
+ } else {
+ --_displayedDirectory;
+ dirEntryDelta = -1;
+ changeDirectoryEntry = true;
+ }
+ } else if (_dirButtonID != -1 && buttonNr == _dirButtonID) {
+ if (!_isShowingDirectory) {
+ directorySwitch = true;
+ }
+ } else {
+ if (_isShowingDirectory || !_calledNumber.size()) {
+ _isShowingDirectory = false;
+ _displayedDirectory = 0;
+ _drawSurface.fillRect(_displayDest, _drawSurface.getTransparentColor());
+ }
+
+ _calledNumber.push_back(buttonNr);
+ _checkNumbers = _dialAutomatically;
+ _animIsStopped = true;
+
+ if (_calledNumber.size() > 11) {
+ _calledNumber.clear();
+
+ if (_hasDisplay) {
+ _drawSurface.fillRect(_displayDest, _drawSurface.getTransparentColor());
+ } else if (_isNewPhone) {
+ NancySceneState.getTextbox().clear();
+ }
+
+ _checkNumbers = false;
+ }
+
+ if (_isNewPhone && _calledNumber.size()) {
+ Common::String numberString;
+ for (uint j = 0; j < _calledNumber.size(); ++j) {
+ numberString += '0' + _calledNumber[j];
+ }
+
+ if (_hasDisplay) {
+ _font->drawString(&_drawSurface, numberString, _displayDest.left + 19, _displayDest.top + 21 - _font->getFontHeight(),
+ _displayDest.width() - 20, 0);
+ } else {
+ NancySceneState.getTextbox().clear();
+ NancySceneState.getTextbox().addTextLine(numberString);
+ }
+ }
+ }
+
+ if (directorySwitch) {
+ // Handle switch to directory mode
+ _isShowingDirectory = true;
+ changeDirectoryEntry = true;
+ _calledNumber.clear();
+ }
+
+ if (changeDirectoryEntry) {
+ int start = _displayedDirectory;
+
+ do {
+ if (_displayedDirectory >= (int)_calls.size()) {
+ _displayedDirectory = 0;
+ } else if (_displayedDirectory < 0) {
+ _displayedDirectory = _calls.size() - 1;
+ }
+
+ if (_calls[_displayedDirectory].eventFlagCondition == kEvNoEvent) {
+ break;
+ }
+
+ if (NancySceneState.getEventFlag(_calls[_displayedDirectory].eventFlagCondition, g_nancy->_true)) {
+ break;
+ }
+
+ _displayedDirectory += dirEntryDelta;
+ } while (_displayedDirectory != start);
+ }
+
_genericButtonSound.name = _buttonSoundNames[buttonNr];
g_nancy->_sound->loadSound(_genericButtonSound);
g_nancy->_sound->playSound(_genericButtonSound);
- drawButton(buttonNr);
+ _drawSurface.blitFrom(_image, _srcRects[buttonNr], _destRects[buttonNr]);
+ _needsRedraw = true;
+
+ _displayAnimEnd = 0;
+ _displayAnimFrame = 0;
_buttonLastPushed = buttonNr;
- _checkNumbers = true;
_callState = kButtonPress;
}
}
}
-void Telephone::drawButton(uint id) {
- Common::Point destPoint(_destRects[id].left - _screenPosition.left, _destRects[id].top - _screenPosition.top);
- _drawSurface.blitFrom(_image, _srcRects[id], destPoint);
-
- _needsRedraw = true;
-}
-
-void Telephone::undrawButton(uint id) {
- Common::Rect bounds = _destRects[id];
- bounds.translate(-_screenPosition.left, -_screenPosition.top);
-
- _drawSurface.fillRect(bounds, g_nancy->_graphics->getTransColor());
- _needsRedraw = true;
-}
-
} // End of namespace Action
} // End of namespace Nancy
diff --git a/engines/nancy/action/puzzle/telephone.h b/engines/nancy/action/puzzle/telephone.h
index e36f007536a..0596727496f 100644
--- a/engines/nancy/action/puzzle/telephone.h
+++ b/engines/nancy/action/puzzle/telephone.h
@@ -25,6 +25,9 @@
#include "engines/nancy/action/actionrecord.h"
namespace Nancy {
+
+class Font;
+
namespace Action {
class Telephone : public RenderActionRecord {
@@ -34,16 +37,23 @@ public:
Common::String soundName;
Common::String text;
SceneChangeWithFlag sceneChange;
+
+ // NewPhone members
+ int16 eventFlagCondition = -1;
+ Common::Rect displaySrc;
};
- enum CallState { kWaiting, kButtonPress, kRinging, kBadNumber, kCall, kHangUp };
+ enum CallState { kWaiting, kButtonPress, kRinging, kBadNumber, kPreCall, kCall, kHangUp };
- Telephone() :
+ Telephone(bool isNewPhone) :
RenderActionRecord(7),
_callState(kWaiting),
_buttonLastPushed(-1),
_selected(-1),
- _checkNumbers(false) {}
+ _checkNumbers(false),
+ _font(nullptr),
+ _animIsStopped(false),
+ _isNewPhone(isNewPhone) {}
virtual ~Telephone() {}
void init() override;
@@ -52,6 +62,10 @@ public:
void execute() override;
void handleInput(NancyInput &input) override;
+protected:
+ Common::String getRecordTypeName() const override { return _isNewPhone ? "NewPhone" : "Telephone"; }
+ bool isViewportRelative() const override { return true; }
+
Common::Path _imageName;
Common::Array<Common::Rect> _srcRects;
Common::Array<Common::Rect> _destRects;
@@ -69,19 +83,45 @@ public:
Common::Rect _exitHotspot;
Common::Array<PhoneCall> _calls;
+ // NewPhone properties
+ bool _hasDisplay = false;
+ uint16 _displayFont = 0;
+ Common::Path _displayAnimName;
+ uint32 _displayAnimFrameTime = 0;
+ Common::Array<Common::Rect> _displaySrcs;
+ Common::Rect _displayDest;
+
+ bool _dialAutomatically = true;
+
+ Common::Rect _dirHighlightSrc;
+ Common::Rect _dialHighlightSrc;
+
+ int16 _upDirButtonID = -1;
+ int16 _downDirButtonID = -1;
+ int16 _dialButtonID = -1;
+ int16 _dirButtonID = -1;
+
+ Common::Rect _displayDialingSrc;
+
+ SoundDescription _preCallSound;
+
Common::Array<byte> _calledNumber;
Graphics::ManagedSurface _image;
+ Graphics::ManagedSurface _animImage;
CallState _callState;
int _buttonLastPushed;
int _selected;
bool _checkNumbers;
+ bool _animIsStopped;
-protected:
- Common::String getRecordTypeName() const override { return "Telephone"; }
- bool isViewportRelative() const override { return true; }
+ uint32 _displayAnimEnd = 0;
+ uint16 _displayAnimFrame = 0;
+ int16 _displayedDirectory = 0;
+ bool _isShowingDirectory = false;
+
+ const Font *_font;
- void drawButton(uint id);
- void undrawButton(uint id);
+ bool _isNewPhone;
};
} // End of namespace Action
diff --git a/engines/nancy/resource.cpp b/engines/nancy/resource.cpp
index c549e0cd3aa..663eca3dde1 100644
--- a/engines/nancy/resource.cpp
+++ b/engines/nancy/resource.cpp
@@ -36,6 +36,10 @@ static char treePrefix[] = "_tree_";
namespace Nancy {
bool ResourceManager::loadImage(const Common::Path &name, Graphics::ManagedSurface &surf, const Common::String &treeName, Common::Rect *outSrc, Common::Rect *outDest) {
+ if (name.empty()) {
+ return false;
+ }
+
// Detect and load autotext surfaces
Common::String baseName(name.baseName());
if (baseName.hasPrefixIgnoreCase("USE_")) {
Commit: 4b274641fb88d0873ef36a3dcc844461c68f5d46
https://github.com/scummvm/scummvm/commit/4b274641fb88d0873ef36a3dcc844461c68f5d46
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2024-02-18T22:31:13+01:00
Commit Message:
DEVTOOLS: Fix typos in nancy.dat
Changed paths:
devtools/create_nancy/nancy4_data.h
devtools/create_nancy/nancy5_data.h
diff --git a/devtools/create_nancy/nancy4_data.h b/devtools/create_nancy/nancy4_data.h
index 93986530f16..984a40cc1d0 100644
--- a/devtools/create_nancy/nancy4_data.h
+++ b/devtools/create_nancy/nancy4_data.h
@@ -30,7 +30,7 @@ const GameConstants _nancy4Constants ={
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // genericEventFlags
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
- 13, // numCursorTypes
+ 12, // numCursorTypes
4000, // logoEndAfter
32 // wonGameFlagID
};
diff --git a/devtools/create_nancy/nancy5_data.h b/devtools/create_nancy/nancy5_data.h
index c62006c4910..5cdeaf2cb23 100644
--- a/devtools/create_nancy/nancy5_data.h
+++ b/devtools/create_nancy/nancy5_data.h
@@ -30,7 +30,7 @@ const GameConstants _nancy5Constants ={
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // genericEventFlags
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
- 13, // numCursorTypes
+ 12, // numCursorTypes
4000, // logoEndAfter
32 // wonGameFlagID
};
More information about the Scummvm-git-logs
mailing list