aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/script_patches.cpp47
-rw-r--r--engines/sludge/fonttext.h2
-rw-r--r--engines/titanic/core/view_item.cpp53
-rw-r--r--engines/titanic/events.cpp17
-rw-r--r--engines/titanic/game/computer_screen.cpp14
-rw-r--r--engines/titanic/game/computer_screen.h1
-rw-r--r--engines/titanic/game/transport/lift.cpp12
-rw-r--r--engines/titanic/messages/messages.h1
-rw-r--r--engines/titanic/moves/move_player_in_parrot_room.cpp12
-rw-r--r--engines/titanic/moves/move_player_in_parrot_room.h9
-rw-r--r--engines/titanic/npcs/bilge_succubus.cpp9
-rw-r--r--engines/titanic/npcs/succubus.cpp15
-rw-r--r--engines/titanic/npcs/succubus.h2
-rw-r--r--engines/titanic/star_control/star_control.h5
-rw-r--r--engines/titanic/star_control/star_view.cpp7
-rw-r--r--engines/titanic/star_control/star_view.h6
16 files changed, 158 insertions, 54 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 5e85c39f51..5ef75f86a8 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -4092,6 +4092,52 @@ static const SciScriptPatcherEntry pq3Signatures[] = {
#pragma mark -
#pragma mark Police Quest 4
+// In Police Quest 4 inside the Bitty Kitty show (room 315), the player has to first talk with a young woman, show her the police badge, then
+// show her the red shoe. She will tell the player that may "Barbie" knows more.
+// After leaving and entering later (not detailed here), Barbie will be available.
+// Now the player needs to show her the police badge as well and then it goes a bit weird.
+//
+// The player can show her the red shoe immediately, which will work dialog-wise, but points won't be awarded and the corresponding flag will also not get set.
+// Internally the game checks if some regular talking dialog (for Barbie) has been accessed before awarding the points and setting the flags.
+// When the player does not recognize this, the player may get stuck and it will look as if a game breaking glitch has happened.
+//
+// Showing the red shoe to the young woman AND showing it to Barbie is all done using the same script.
+// It works via shoeShoe::changeState.
+//
+// The code in there of state 0 checks first who is currently inside the room using stripper::noun.
+// Afterwards for the young woman it checks local 3 if it's zero or not zero.
+// Local 3 is set, when the player has shown the police badge to the person, that is currently inside the room.
+//
+// For Barbie strangely global 9Ah is checked instead, which then causes those issues.
+//
+// We change the Barbie code to also check local 3, which seems to work out.
+// We can't simply remove the check, otherwise the flag will get set even when the player
+// hasn't shown the badge, which will cause Barbie to not answer the question and the player
+// won't be able to show her the shoe a second time.
+//
+// This of course also happened, when using the original interpreter.
+//
+// Applies to at least: English floppy, German floppy, English CD
+// Responsible method: showShoe::changeState(0) - script 315
+// Fixes bug: #9849
+static const uint16 pq4BittyKittyShowBarieRedShoeSignature[] = {
+ // stripper::noun check is for checking, if police badge was shown
+ SIG_MAGICDWORD,
+ 0x89, 0x9a, // lsg global[9Ah]
+ 0x35, 0x02, // ldi 02
+ 0x1e, // gt?
+ 0x30, SIG_UINT16(0x0028), // bnt [skip 2 points code]
+ 0x39, 0x61, // pushi 61h (flag)
+ SIG_END
+};
+
+static const uint16 pq4BittyKittyShowBarbieRedShoePatch[] = {
+ 0x83, 0x03, // lal local[3]
+ 0x30, PATCH_UINT16(0x002b), // bnt [skip 2 points code]
+ 0x33, 1, // jmp 1 (waste some bytes)
+ PATCH_END
+};
+
// In Police Quest 4 scripts for room 390 (city hall) use ticks instead of seconds.
// Ticks are not behaving the same as seconds. Ticks will also go down within game menus including inventory.
// When getting attacked, the player has almost no time to draw the gun - and even when the player has the gun
@@ -4182,6 +4228,7 @@ static const uint16 pq4FloppyCityHallCuffEnemyTimerPatch[] = {
// script, description, signature patch
static const SciScriptPatcherEntry pq4Signatures[] = {
+ { true, 315, "show barbie the red shoe points fix", 1, pq4BittyKittyShowBarieRedShoeSignature, pq4BittyKittyShowBarbieRedShoePatch },
{ true, 390, "floppy: city hall: draw gun timer", 1, pq4FloppyCityHallDrawGunTimerSignature, pq4FloppyCityHallDrawGunTimerPatch },
{ true, 390, "floppy: city hall: tell enemy drop weapon timer", 1, pq4FloppyCityHallTellEnemyDropWeaponTimerSignature, pq4FloppyCityHallTellEnemyDropWeaponTimerPatch },
{ true, 390, "floppy: city hall: tell enemy turn around timer", 1, pq4FloppyCityHallTellEnemyTurnAroundTimerSignature, pq4FloppyCityHallTellEnemyTurnAroundTimerPatch },
diff --git a/engines/sludge/fonttext.h b/engines/sludge/fonttext.h
index c8038cb28d..3170a3e12f 100644
--- a/engines/sludge/fonttext.h
+++ b/engines/sludge/fonttext.h
@@ -30,7 +30,7 @@
namespace Sludge {
struct SpriteBank;
-struct SpritePalette;
+class SpritePalette;
class TextManager {
public:
diff --git a/engines/titanic/core/view_item.cpp b/engines/titanic/core/view_item.cpp
index 401553d55d..f98b015feb 100644
--- a/engines/titanic/core/view_item.cpp
+++ b/engines/titanic/core/view_item.cpp
@@ -340,6 +340,7 @@ CString CViewItem::getNodeViewName() const {
bool CViewItem::MovementMsg(CMovementMsg *msg) {
Point pt;
+ bool foundPt = false;
// First allow any child objects to handle it
for (CTreeItem *treeItem = getFirstChild(); treeItem;
@@ -348,31 +349,41 @@ bool CViewItem::MovementMsg(CMovementMsg *msg) {
return true;
}
- // Iterate through the view's contents to find a link or item
- // with the appropriate movement action
- for (CTreeItem *treeItem = getFirstChild(); treeItem;
- treeItem = treeItem->scan(this)) {
- CLinkItem *link = dynamic_cast<CLinkItem *>(treeItem);
- CGameObject *gameObj = dynamic_cast<CGameObject *>(treeItem);
-
- if (link) {
- // Skip links that aren't for the desired direction
- if (link->getMovement() != msg->_movement)
- continue;
-
- pt = Point((link->_bounds.left + link->_bounds.right) / 2,
- (link->_bounds.top + link->_bounds.bottom) / 2);
- } else if (gameObj) {
- if (!gameObj->_visible || gameObj->getMovement() != msg->_movement)
+ if (msg->_posToUse.x != 0 || msg->_posToUse.y != 0) {
+ pt = msg->_posToUse;
+ foundPt = true;
+ } else {
+ // Iterate through the view's contents to find a link or item
+ // with the appropriate movement action
+ for (CTreeItem *treeItem = getFirstChild(); treeItem;
+ treeItem = treeItem->scan(this)) {
+ CLinkItem *link = dynamic_cast<CLinkItem *>(treeItem);
+ CGameObject *gameObj = dynamic_cast<CGameObject *>(treeItem);
+
+ if (link) {
+ // Skip links that aren't for the desired direction
+ if (link->getMovement() != msg->_movement)
+ continue;
+
+ pt = Point((link->_bounds.left + link->_bounds.right) / 2,
+ (link->_bounds.top + link->_bounds.bottom) / 2);
+ } else if (gameObj) {
+ if (!gameObj->_visible || gameObj->getMovement() != msg->_movement)
+ continue;
+
+ if (!gameObj->findPoint(pt))
+ continue;
+ } else {
+ // Not a link or object, so ignore
continue;
+ }
- if (!gameObj->findPoint(pt))
- continue;
- } else {
- // Not a link or object, so ignore
- continue;
+ foundPt = true;
+ break;
}
+ }
+ if (foundPt) {
// We've found a point on the object or link that has a
// cursor for the given direction. So simulate a mouse
// press and release on the desired point
diff --git a/engines/titanic/events.cpp b/engines/titanic/events.cpp
index f554796d09..f946f7b214 100644
--- a/engines/titanic/events.cpp
+++ b/engines/titanic/events.cpp
@@ -27,6 +27,7 @@
#include "titanic/events.h"
#include "titanic/titanic.h"
#include "titanic/main_game_window.h"
+#include "titanic/star_control/star_control.h"
namespace Titanic {
@@ -108,10 +109,22 @@ void Events::pollEventsAndWait() {
pollEvents();
g_system->delayMillis(10);
- // Regularly update the sound mixer
CGameManager *gameManager = g_vm->_window->_gameManager;
- if (gameManager)
+ if (gameManager) {
+ // Regularly update the sound mixer
gameManager->_sound.updateMixer();
+
+ // WORKAROUND: If in the Star Control view, update the camera
+ // frequently, to accomodate that the original had a higher
+ // draw rate than the ScummVM implementation does
+ CViewItem *view = gameManager->getView();
+ if (view->getFullViewName() == "Bridge.Node 4.N") {
+ CStarControl *starControl = dynamic_cast<CStarControl *>(
+ view->findChildInstanceOf(CStarControl::_type));
+ if (starControl && starControl->_visible)
+ starControl->updateCamera();
+ }
+ }
}
bool Events::checkForNextFrameCounter() {
diff --git a/engines/titanic/game/computer_screen.cpp b/engines/titanic/game/computer_screen.cpp
index be9c87a540..179063d1b0 100644
--- a/engines/titanic/game/computer_screen.cpp
+++ b/engines/titanic/game/computer_screen.cpp
@@ -31,6 +31,7 @@ BEGIN_MESSAGE_MAP(CComputerScreen, CGameObject)
ON_MESSAGE(MovieEndMsg)
ON_MESSAGE(EnterViewMsg)
ON_MESSAGE(TimerMsg)
+ ON_MESSAGE(MovementMsg)
END_MESSAGE_MAP()
CComputerScreen::CComputerScreen() : CGameObject() {
@@ -68,9 +69,22 @@ bool CComputerScreen::MovieEndMsg(CMovieEndMsg *msg) {
bool CComputerScreen::EnterViewMsg(CEnterViewMsg *msg) {
loadFrame(26);
+
+ // WORKAROUND: The original game leaves in a debug link that
+ // allows skipping of Doorbot arrival sequence. Disable it
+ static_cast<CLinkItem *>(getParent()->findByName("_TRACK,3,e-cu,4,E"))->_bounds.clear();
+
return true;
}
+bool CComputerScreen::MovementMsg(CMovementMsg *msg) {
+ if (msg->_movement != MOVE_BACKWARDS)
+ return true;
+
+ msg->_posToUse = Common::Point(320, 50);
+ return false;
+}
+
bool CComputerScreen::TimerMsg(CTimerMsg *msg) {
int handle;
diff --git a/engines/titanic/game/computer_screen.h b/engines/titanic/game/computer_screen.h
index 8fb1dcd4dc..8affef3aed 100644
--- a/engines/titanic/game/computer_screen.h
+++ b/engines/titanic/game/computer_screen.h
@@ -33,6 +33,7 @@ class CComputerScreen : public CGameObject {
bool MovieEndMsg(CMovieEndMsg *msg);
bool EnterViewMsg(CEnterViewMsg *msg);
bool TimerMsg(CTimerMsg *msg);
+ bool MovementMsg(CMovementMsg *msg);
public:
CLASSDEF;
CComputerScreen();
diff --git a/engines/titanic/game/transport/lift.cpp b/engines/titanic/game/transport/lift.cpp
index ca5b74467a..17f1783494 100644
--- a/engines/titanic/game/transport/lift.cpp
+++ b/engines/titanic/game/transport/lift.cpp
@@ -22,6 +22,7 @@
#include "titanic/game/transport/lift.h"
#include "titanic/pet_control/pet_control.h"
+#include "titanic/moves/multi_move.h"
#include "titanic/titanic.h"
namespace Titanic {
@@ -289,6 +290,17 @@ bool CLift::ActMsg(CActMsg *msg) {
actMsg1.execute("RPanInLiftW");
CActMsg actMsg2("Lift.Node 2.S");
actMsg2.execute("LPanInLiftW");
+
+ // WORKAROUND: In the original, when Lift 4's head is removed, the other
+ // view directions use Node 2. These "removed" views have links, but their
+ // movement cursors weren't correctly set. This fixes them
+ CNamedItem *node2 = findRoom()->findByName("Node 2");
+ static_cast<CMultiMove *>(node2->findByName("LMultiLiftPan"))->_cursorId = CURSOR_MOVE_LEFT;
+ static_cast<CLinkItem *>(node2->findByName("_PANR,2,N,E"))->_cursorId = CURSOR_MOVE_RIGHT;
+ static_cast<CLinkItem *>(node2->findByName("_PANL,2,E,N"))->_cursorId = CURSOR_MOVE_LEFT;
+ static_cast<CLinkItem *>(node2->findByName("_PANR,2,E,S"))->_cursorId = CURSOR_MOVE_RIGHT;
+ static_cast<CLinkItem *>(node2->findByName("_PANL,2,S,E"))->_cursorId = CURSOR_MOVE_LEFT;
+ static_cast<CMultiMove *>(node2->findByName("RMultiLiftPan"))->_cursorId = CURSOR_MOVE_RIGHT;
} else if (msg->_action == "AddWrongHead") {
_hasHead = true;
_hasCorrectHead = false;
diff --git a/engines/titanic/messages/messages.h b/engines/titanic/messages/messages.h
index b5c8dd4e21..115976a70d 100644
--- a/engines/titanic/messages/messages.h
+++ b/engines/titanic/messages/messages.h
@@ -230,6 +230,7 @@ enum Movement {
class CMovementMsg : public CMessage {
public:
Movement _movement;
+ Point _posToUse;
public:
CLASSDEF;
CMovementMsg() : _movement(MOVE_NONE) {}
diff --git a/engines/titanic/moves/move_player_in_parrot_room.cpp b/engines/titanic/moves/move_player_in_parrot_room.cpp
index 186e448bba..dfe8cf547e 100644
--- a/engines/titanic/moves/move_player_in_parrot_room.cpp
+++ b/engines/titanic/moves/move_player_in_parrot_room.cpp
@@ -27,6 +27,7 @@ namespace Titanic {
BEGIN_MESSAGE_MAP(CMovePlayerInParrotRoom, CMovePlayerTo)
ON_MESSAGE(ActMsg)
ON_MESSAGE(MouseButtonDownMsg)
+ ON_MESSAGE(MovementMsg)
END_MESSAGE_MAP()
CMovePlayerInParrotRoom::CMovePlayerInParrotRoom() : CMovePlayerTo() {
@@ -58,13 +59,10 @@ bool CMovePlayerInParrotRoom::MouseButtonDownMsg(CMouseButtonDownMsg *msg) {
return true;
}
-bool CMovePlayerInParrotRoom::findPoint(Point &pt) {
- if (_destination == "ParrotLobby.Node 1.E") {
- pt = Point(600, 180);
- return true;
- } else {
- return CMovePlayerTo::findPoint(pt);
- }
+bool CMovePlayerInParrotRoom::MovementMsg(CMovementMsg *msg) {
+ if (msg->_movement == TURN_RIGHT)
+ msg->_posToUse = Point(600, 180);
+ return false;
}
} // End of namespace Titanic
diff --git a/engines/titanic/moves/move_player_in_parrot_room.h b/engines/titanic/moves/move_player_in_parrot_room.h
index 50a0b2a00e..637c8b8211 100644
--- a/engines/titanic/moves/move_player_in_parrot_room.h
+++ b/engines/titanic/moves/move_player_in_parrot_room.h
@@ -31,6 +31,7 @@ class CMovePlayerInParrotRoom : public CMovePlayerTo {
DECLARE_MESSAGE_MAP;
bool ActMsg(CActMsg *msg);
bool MouseButtonDownMsg(CMouseButtonDownMsg *msg);
+ bool MovementMsg(CMovementMsg *msg);
public:
CLASSDEF;
CMovePlayerInParrotRoom();
@@ -44,14 +45,6 @@ public:
* Load the data for the class from file
*/
virtual void load(SimpleFile *file);
-
- /**
- * Returns a point that falls within the object. Used for simulating
- * mouse clicks for movement when arrow keys are pressed
- * @param pt Return point
- * @returns True if a point was found
- */
- virtual bool findPoint(Point &pt);
};
} // End of namespace Titanic
diff --git a/engines/titanic/npcs/bilge_succubus.cpp b/engines/titanic/npcs/bilge_succubus.cpp
index 84baa1865c..a1fc46874c 100644
--- a/engines/titanic/npcs/bilge_succubus.cpp
+++ b/engines/titanic/npcs/bilge_succubus.cpp
@@ -73,7 +73,8 @@ bool CBilgeSuccUBus::FrameMsg(CFrameMsg *msg) {
bool CBilgeSuccUBus::PETReceiveMsg(CPETReceiveMsg *msg) {
CPetControl *pet = getPetControl();
- if (_style) {
+ if (_motherBlocked) {
+ // Mother hasn't yet been unblocked, so don't receive anything
if (_receiveStartFrame >= 0)
playMovie(_receiveStartFrame, _receiveEndFrame, MOVIE_WAIT_FOR_FINISH);
if (_afterReceiveStartFrame >= 0)
@@ -130,7 +131,7 @@ bool CBilgeSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) {
_isFeathers = mailObject->getName() == "Feathers";
_sendAction = SA_SENT;
- if (_style) {
+ if (_motherBlocked) {
if (_isFeathers) {
startTalking(this, 230022);
_sendAction = SA_FEATHERS;
@@ -189,7 +190,7 @@ bool CBilgeSuccUBus::MovieEndMsg(CMovieEndMsg *msg) {
playSound("z#30.wav");
} else {
if (msg->_endFrame == _onEndFrame && pet) {
- if (_style) {
+ if (_motherBlocked) {
startTalking(this, getRandomNumber(1) ? 230062 : 230063);
} else if (!findMail(pet->getRoomFlags())) {
switch (getRandomNumber(4)) {
@@ -254,7 +255,7 @@ bool CBilgeSuccUBus::MovieEndMsg(CMovieEndMsg *msg) {
} else if (msg->_endFrame == _sneezing2EndFrame) {
changeView("BilgeRoomWith.Node 1.N", "");
- _style = false;
+ _motherBlocked = false;
resetMail();
if (_mailP) {
diff --git a/engines/titanic/npcs/succubus.cpp b/engines/titanic/npcs/succubus.cpp
index ef681f64b8..522269b41b 100644
--- a/engines/titanic/npcs/succubus.cpp
+++ b/engines/titanic/npcs/succubus.cpp
@@ -47,7 +47,7 @@ BEGIN_MESSAGE_MAP(CSuccUBus, CTrueTalkNPC)
END_MESSAGE_MAP()
bool CSuccUBus::_isOn;
-bool CSuccUBus::_style;
+bool CSuccUBus::_motherBlocked;
bool CSuccUBus::_enabled;
CSuccUBus::CSuccUBus() : CTrueTalkNPC() {
@@ -118,7 +118,7 @@ void CSuccUBus::save(SimpleFile *file, int indent) {
file->writeNumberLine(_okEndFrame, indent);
file->writeNumberLine(_flagsComparison, indent);
- file->writeNumberLine(_style, indent);
+ file->writeNumberLine(_motherBlocked, indent);
file->writeNumberLine(_afterReceiveStartFrame, indent);
file->writeNumberLine(_afterReceiveEndFrame, indent);
file->writeNumberLine(_trayOutStartFrame, indent);
@@ -181,7 +181,7 @@ void CSuccUBus::load(SimpleFile *file) {
_okEndFrame = file->readNumber();
_flagsComparison = (RoomFlagsComparison)file->readNumber();
- _style = file->readNumber();
+ _motherBlocked = file->readNumber();
_afterReceiveStartFrame = file->readNumber();
_afterReceiveEndFrame = file->readNumber();
_trayOutStartFrame = file->readNumber();
@@ -385,9 +385,10 @@ bool CSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) {
if (!pet)
return true;
- uint destRoomFlags = pet->getRoomFlags();
- CGameObject *mailObject = findMail(destRoomFlags);
+ uint srcRoomFlags = pet->getRoomFlags();
+ CGameObject *mailObject = findMail(srcRoomFlags);
if (!mailObject) {
+ // Nothing to send
switch (getRandomNumber(2)) {
case 0:
startTalking(this, 70111, findView());
@@ -422,7 +423,7 @@ bool CSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) {
if (_isFeathers) {
// The feather has special handling to be rejected by the SuccUBus
_sendLost = false;
- sendMail(destRoomFlags, roomFlags);
+ sendMail(srcRoomFlags, roomFlags);
pet->phonographAction("");
if (_okStartFrame >= 0) {
@@ -570,7 +571,7 @@ bool CSuccUBus::MovieEndMsg(CMovieEndMsg *msg) {
stopSound(_soundHandle);
_soundHandle = -1;
- switch (getRandomNumber(_style ? 7 : 5, &_priorRandomVal2)) {
+ switch (getRandomNumber(_motherBlocked ? 7 : 5, &_priorRandomVal2)) {
case 2:
startTalking(this, 230001, findView());
break;
diff --git a/engines/titanic/npcs/succubus.h b/engines/titanic/npcs/succubus.h
index 483ef54f47..94e0bebe54 100644
--- a/engines/titanic/npcs/succubus.h
+++ b/engines/titanic/npcs/succubus.h
@@ -50,7 +50,7 @@ class CSuccUBus : public CTrueTalkNPC {
bool MouseDragStartMsg(CMouseDragStartMsg *msg);
protected:
static bool _isOn;
- static bool _style;
+ static bool _motherBlocked;
static bool _enabled;
protected:
int _initialStartFrame;
diff --git a/engines/titanic/star_control/star_control.h b/engines/titanic/star_control/star_control.h
index 8013eed850..90de2eb3eb 100644
--- a/engines/titanic/star_control/star_control.h
+++ b/engines/titanic/star_control/star_control.h
@@ -97,6 +97,11 @@ public:
* Called when a star destination is set
*/
void starDestinationSet();
+
+ /**
+ * Updates the camerea for the star view
+ */
+ void updateCamera() { _view.updateCamera(); }
};
} // End of namespace Titanic
diff --git a/engines/titanic/star_control/star_view.cpp b/engines/titanic/star_control/star_view.cpp
index 576fd87b54..465e974d44 100644
--- a/engines/titanic/star_control/star_view.cpp
+++ b/engines/titanic/star_control/star_view.cpp
@@ -97,7 +97,7 @@ void CStarView::draw(CScreenManager *screenManager) {
if (_homePhotoMask)
_homePhotoMask->draw(screenManager, Point(20, 187));
} else {
- fn1();
+ updateCamera();
// Render the display
_videoSurface->clear();
@@ -255,7 +255,10 @@ void CStarView::resetPosition() {
_camera.setPosition(FVector(0.0, 0.0, 0.0));
}
-bool CStarView::fn1() {
+bool CStarView::updateCamera() {
+ if (_fader.isActive() || _showingPhoto)
+ return false;
+
if (_videoSurface) {
CErrorCode errorCode;
_camera.updatePosition(&errorCode);
diff --git a/engines/titanic/star_control/star_view.h b/engines/titanic/star_control/star_view.h
index a98886eb51..204c02336c 100644
--- a/engines/titanic/star_control/star_view.h
+++ b/engines/titanic/star_control/star_view.h
@@ -50,7 +50,6 @@ private:
bool _field218;
bool _showingPhoto;
private:
- bool fn1();
void fn18(CStarCamera *camera);
void fn19(int v);
@@ -95,6 +94,11 @@ public:
void draw(CScreenManager *screenManager);
/**
+ * Updates the camera, allowing for movement
+ */
+ bool updateCamera();
+
+ /**
* Handles mouse down messages
*/
bool MouseButtonDownMsg(int unused, const Point &pt);