aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/avalanche/animation.cpp5
-rw-r--r--engines/avalanche/avalanche.cpp12
-rw-r--r--engines/avalanche/avalanche.h8
-rw-r--r--engines/avalanche/background.cpp16
-rw-r--r--engines/avalanche/background.h2
-rw-r--r--engines/avalanche/enums.h6
-rw-r--r--engines/avalanche/ghostroom.cpp364
-rw-r--r--engines/avalanche/ghostroom.h88
-rw-r--r--engines/avalanche/graphics.cpp259
-rw-r--r--engines/avalanche/graphics.h24
-rw-r--r--engines/avalanche/help.cpp268
-rw-r--r--engines/avalanche/help.h65
-rw-r--r--engines/avalanche/module.mk6
-rw-r--r--engines/avalanche/parser.cpp3
-rw-r--r--engines/avalanche/pingo.cpp94
-rw-r--r--engines/avalanche/shootemup.cpp175
-rw-r--r--engines/avalanche/shootemup.h76
-rw-r--r--engines/avalanche/timer.cpp43
-rw-r--r--engines/cge/cge_main.cpp5
-rw-r--r--engines/cge/detection.cpp53
-rw-r--r--engines/cge/vga13h.cpp9
-rw-r--r--engines/cine/gfx.cpp27
-rw-r--r--engines/cine/main_loop.cpp2
-rw-r--r--engines/fullpipe/constants.h83
-rw-r--r--engines/fullpipe/fullpipe.h5
-rw-r--r--engines/fullpipe/gfx.cpp5
-rw-r--r--engines/fullpipe/init.cpp2
-rw-r--r--engines/fullpipe/inventory.cpp24
-rw-r--r--engines/fullpipe/lift.cpp267
-rw-r--r--engines/fullpipe/messages.cpp17
-rw-r--r--engines/fullpipe/messages.h2
-rw-r--r--engines/fullpipe/modal.cpp69
-rw-r--r--engines/fullpipe/modal.h47
-rw-r--r--engines/fullpipe/module.mk2
-rw-r--r--engines/fullpipe/motion.cpp234
-rw-r--r--engines/fullpipe/motion.h2
-rw-r--r--engines/fullpipe/objectnames.h8
-rw-r--r--engines/fullpipe/scenes.cpp69
-rw-r--r--engines/fullpipe/scenes.h76
-rw-r--r--engines/fullpipe/scenes/scene03.cpp4
-rw-r--r--engines/fullpipe/scenes/scene06.cpp4
-rw-r--r--engines/fullpipe/scenes/scene09.cpp484
-rw-r--r--engines/fullpipe/scenes/scene10.cpp4
-rw-r--r--engines/fullpipe/scenes/scene14.cpp4
-rw-r--r--engines/fullpipe/scenes/scene15.cpp4
-rw-r--r--engines/fullpipe/scenes/scene27.cpp759
-rw-r--r--engines/fullpipe/scenes/scene30.cpp4
-rw-r--r--engines/fullpipe/scenes/scene32.cpp4
-rw-r--r--engines/fullpipe/scenes/scene34.cpp4
-rw-r--r--engines/fullpipe/scenes/scene35.cpp4
-rw-r--r--engines/fullpipe/scenes/scene38.cpp4
-rw-r--r--engines/gob/detection/tables.h2
-rw-r--r--engines/gob/detection/tables_crousti.h (renamed from engines/avalanche/pingo.h)57
-rw-r--r--engines/gob/draw_fascin.cpp4
-rw-r--r--engines/gob/gob.cpp1
-rw-r--r--engines/gob/gob.h4
-rw-r--r--engines/gob/inter.h2
-rw-r--r--engines/gob/inter_v2.cpp183
-rw-r--r--engines/gob/inter_v3.cpp183
-rw-r--r--engines/hopkins/anim.cpp3
-rw-r--r--engines/hopkins/computer.cpp12
-rw-r--r--engines/hopkins/detection.cpp27
-rw-r--r--engines/hopkins/detection_tables.h41
-rw-r--r--engines/hopkins/files.cpp16
-rw-r--r--engines/hopkins/graphics.cpp6
-rw-r--r--engines/hopkins/hopkins.cpp7
-rw-r--r--engines/hopkins/lines.cpp15
-rw-r--r--engines/hopkins/objects.cpp8
-rw-r--r--engines/hopkins/sound.cpp8
-rw-r--r--engines/hopkins/sound.h8
-rw-r--r--engines/hopkins/talk.cpp1
-rw-r--r--engines/hugo/detection.cpp3
-rw-r--r--engines/hugo/dialogs.cpp1
-rw-r--r--engines/hugo/mouse.cpp9
-rw-r--r--engines/hugo/object.cpp12
-rw-r--r--engines/hugo/route.cpp4
-rw-r--r--engines/hugo/schedule.cpp14
-rw-r--r--engines/hugo/text.cpp6
-rw-r--r--engines/kyra/sequences_hof.cpp2
-rw-r--r--engines/kyra/timer_eob.cpp2
-rw-r--r--engines/mortevielle/actions.cpp17
-rw-r--r--engines/mortevielle/dialogs.cpp4
-rw-r--r--engines/mortevielle/mouse.cpp8
-rw-r--r--engines/mortevielle/sound.cpp3
-rw-r--r--engines/mortevielle/utils.cpp2
-rw-r--r--engines/pegasus/neighborhood/tsa/fulltsa.cpp22
-rw-r--r--engines/pegasus/neighborhood/tsa/tinytsa.cpp22
-rw-r--r--engines/queen/detection.cpp512
-rw-r--r--engines/queen/module.mk1
-rw-r--r--engines/queen/queen.cpp183
-rw-r--r--engines/sci/engine/state.cpp2
-rw-r--r--engines/sci/resource.cpp9
-rw-r--r--engines/toon/toon.cpp16
-rw-r--r--engines/touche/menu.cpp10
-rw-r--r--engines/touche/touche.cpp4
-rw-r--r--engines/tsage/blue_force/blueforce_scenes3.cpp2
-rw-r--r--engines/tsage/blue_force/blueforce_scenes5.cpp2
-rw-r--r--engines/tsage/blue_force/blueforce_scenes9.cpp2
-rw-r--r--engines/tsage/core.cpp6
-rw-r--r--engines/tsage/core.h2
-rw-r--r--engines/tsage/graphics.cpp3
-rw-r--r--engines/tsage/ringworld/ringworld_dialogs.cpp3
-rw-r--r--engines/tsage/ringworld/ringworld_scenes10.cpp2
-rw-r--r--engines/tsage/ringworld/ringworld_scenes3.cpp4
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp11
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.h1
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.cpp77
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.h2
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.cpp14
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.cpp4
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.cpp23
-rw-r--r--engines/tucker/tucker.cpp3
-rw-r--r--engines/wintermute/ad/ad_scene.cpp8
-rw-r--r--engines/wintermute/base/font/base_font_truetype.cpp13
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp2
-rw-r--r--engines/wintermute/video/video_theora_player.cpp2
117 files changed, 4577 insertions, 872 deletions
diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp
index 639abe99b3..74dd2100e5 100644
--- a/engines/avalanche/animation.cpp
+++ b/engines/avalanche/animation.cpp
@@ -815,10 +815,9 @@ void Animation::callSpecial(uint16 which) {
}
break;
case 4: // This is the ghost room link.
- _vm->fadeOut();
- _sprites[0]->turn(kDirRight); // you'll see this after we get back from bootstrap
+ _sprites[0]->turn(kDirRight); // You'll see this after we get back.
_vm->_timer->addTimer(1, Timer::kProcGhostRoomPhew, Timer::kReasonGhostRoomPhew);
- //_vm->_enid->backToBootstrap(3); TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then!
+ _vm->_ghostroom->run();
break;
case 5:
if (_vm->_friarWillTieYouUp) {
diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp
index a7e7be0ad3..073b9a9425 100644
--- a/engines/avalanche/avalanche.cpp
+++ b/engines/avalanche/avalanche.cpp
@@ -46,7 +46,6 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription *
_clock = nullptr;
_graphics = nullptr;
_parser = nullptr;
- _pingo = nullptr;
_dialogs = nullptr;
_background = nullptr;
_sequence = nullptr;
@@ -56,6 +55,9 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription *
_closing = nullptr;
_sound = nullptr;
_nim = nullptr;
+ _ghostroom = nullptr;
+ _help = nullptr;
+ _shootemup = nullptr;
_platform = gd->desc.platform;
initVariables();
@@ -69,7 +71,6 @@ AvalancheEngine::~AvalancheEngine() {
delete _parser;
delete _clock;
- delete _pingo;
delete _dialogs;
delete _background;
delete _sequence;
@@ -79,6 +80,9 @@ AvalancheEngine::~AvalancheEngine() {
delete _closing;
delete _sound;
delete _nim;
+ delete _ghostroom;
+ delete _help;
+ delete _shootemup;
for (int i = 0; i < 31; i++) {
for (int j = 0; j < 2; j++) {
@@ -152,7 +156,6 @@ Common::ErrorCode AvalancheEngine::initialize() {
_parser = new Parser(this);
_clock = new Clock(this);
- _pingo = new Pingo(this);
_dialogs = new Dialogs(this);
_background = new Background(this);
_sequence = new Sequence(this);
@@ -162,6 +165,9 @@ Common::ErrorCode AvalancheEngine::initialize() {
_closing = new Closing(this);
_sound = new SoundHandler(this);
_nim = new Nim(this);
+ _ghostroom = new GhostRoom(this);
+ _help = new Help(this);
+ _shootemup = new ShootEmUp(this);
_graphics->init();
_dialogs->init();
diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h
index fe13fa8d9e..d2e5678ae9 100644
--- a/engines/avalanche/avalanche.h
+++ b/engines/avalanche/avalanche.h
@@ -32,7 +32,6 @@
#include "avalanche/graphics.h"
#include "avalanche/parser.h"
#include "avalanche/avalot.h"
-#include "avalanche/pingo.h"
#include "avalanche/dialogs.h"
#include "avalanche/background.h"
#include "avalanche/sequence.h"
@@ -43,6 +42,9 @@
#include "avalanche/sound.h"
#include "avalanche/nim.h"
#include "avalanche/clock.h"
+#include "avalanche/ghostroom.h"
+#include "avalanche/help.h"
+#include "avalanche/shootemup.h"
#include "common/serializer.h"
@@ -77,7 +79,6 @@ public:
Clock *_clock;
GraphicManager *_graphics;
Parser *_parser;
- Pingo *_pingo;
Dialogs *_dialogs;
Background *_background;
Sequence *_sequence;
@@ -87,6 +88,9 @@ public:
Closing *_closing;
SoundHandler *_sound;
Nim *_nim;
+ GhostRoom *_ghostroom;
+ Help *_help;
+ ShootEmUp *_shootemup;
OSystem *_system;
diff --git a/engines/avalanche/background.cpp b/engines/avalanche/background.cpp
index 5d168a20af..f49d103df3 100644
--- a/engines/avalanche/background.cpp
+++ b/engines/avalanche/background.cpp
@@ -279,24 +279,24 @@ void Background::load(byte number) {
sprite._type = (PictureType)(f.readByte());
sprite._x = f.readSint16LE();
sprite._y = f.readSint16LE();
- sprite._xl = f.readSint16LE();
- sprite._yl = f.readSint16LE();
+ sprite._width = f.readSint16LE();
+ sprite._height = f.readSint16LE();
sprite._size = f.readSint32LE();
bool natural = f.readByte();
bool memorize = f.readByte();
if (memorize) {
_sprites[i]._x = sprite._x;
- _sprites[i]._xl = sprite._xl;
+ _sprites[i]._width = sprite._width;
_sprites[i]._y = sprite._y;
- _sprites[i]._yl = sprite._yl;
+ _sprites[i]._height = sprite._height;
_sprites[i]._type = sprite._type;
if (natural)
_vm->_graphics->getNaturalPicture(_sprites[i]);
else {
_sprites[i]._size = sprite._size;
- _sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._xl * 8, _sprites[i]._yl + 1);
+ _sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._width * 8, _sprites[i]._height + 1);
}
} else
_sprites[i]._x = kOnDisk;
@@ -335,11 +335,11 @@ void Background::draw(int16 destX, int16 destY, byte sprId) {
sprite._type = (PictureType)(f.readByte());
sprite._x = f.readSint16LE();
sprite._y = f.readSint16LE();
- sprite._xl = f.readSint16LE();
- sprite._yl = f.readSint16LE();
+ sprite._width = f.readSint16LE();
+ sprite._height = f.readSint16LE();
sprite._size = f.readSint32LE();
f.skip(2); // Natural and Memorize are used in Load()
- sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._xl * 8, sprite._yl + 1);
+ sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._width * 8, sprite._height + 1);
if (destX < 0) {
destX = sprite._x * 8;
diff --git a/engines/avalanche/background.h b/engines/avalanche/background.h
index 34d7a9a2cc..67020c861d 100644
--- a/engines/avalanche/background.h
+++ b/engines/avalanche/background.h
@@ -40,7 +40,7 @@ enum PictureType {kEga, kBgi, kNaturalImage};
struct SpriteType {
PictureType _type;
int16 _x, _y;
- int16 _xl, _yl;
+ int16 _width, _height;
int32 _size;
Graphics::Surface _picture;
};
diff --git a/engines/avalanche/enums.h b/engines/avalanche/enums.h
index 2b5db67609..23192863f1 100644
--- a/engines/avalanche/enums.h
+++ b/engines/avalanche/enums.h
@@ -29,6 +29,10 @@
#define AVALANCHE_ENUMS_H
namespace Avalanche {
+
+
+enum Flavour { kFlavourEga, kFlavourBgi, kFlavourNatural, kFlavourTwo, kFlavourOne };
+
enum Color {
kColorBlack = 0, kColorBlue, kColorGreen, kColorCyan, kColorRed,
kColorMagenta = 5, kColorBrown, kColorLightgray, kColorDarkgray, kColorLightblue,
@@ -87,7 +91,7 @@ enum VerbCode {
enum MouseCursor {
kCurUpArrow = 0, kCurScrewDriver = 1, kCurRightArrow = 2, kCurFletch = 3, kCurWait = 4, kCurHand = 5,
- kCurCrosshair = 6, kCurIBeam = 7
+ kCurCrosshair = 6, kCurIBeam = 7, kCurHelp = 8
};
// Magic/portal constants:
diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp
new file mode 100644
index 0000000000..b67df878ee
--- /dev/null
+++ b/engines/avalanche/ghostroom.cpp
@@ -0,0 +1,364 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman.
+*/
+
+#include "avalanche/avalanche.h"
+#include "avalanche/ghostroom.h"
+
+#include "common/random.h"
+
+namespace Avalanche {
+
+const int8 GhostRoom::kAdjustment[5] = { 7, 0, 7, 7, 7 };
+const byte GhostRoom::kWaveOrder[5] = { 4, 0, 1, 2, 3 };
+const byte GhostRoom::kGlerkFade[26] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 0 };
+const byte GhostRoom::kGreldetFade[18] = { 0, 1, 2, 3, 4, 5, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0 };
+
+GhostRoom::GhostRoom(AvalancheEngine *vm) {
+ _vm = vm;
+
+ _glerkStage = 0;
+ _batX = 0;
+ _batY = 0;
+ _batCount = 0;
+ _aarghCount = 0;
+ _greldetX = _greldetY = 0;
+ _greldetCount = 0;
+ _redGreldet = false;
+ _wasLoaded = false;
+}
+
+GhostRoom::~GhostRoom() {
+ for (int i = 0; i < 2; i++)
+ _eyes[i].free();
+
+ _exclamation.free();
+
+ for (int i = 0; i < 3; i++)
+ _bat[i].free();
+
+ for (int i = 0; i < 6; i++)
+ _aargh[i].free();
+
+ for (int i = 0; i < 5; i++)
+ _greenEyes[i].free();
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 6; j++)
+ _greldet[j][i].free();
+ }
+}
+
+void GhostRoom::wait(uint16 howLong) {
+ for (int i = 0; i < howLong; i++) {
+ Common::Event event;
+ _vm->getEvent(event);
+ if (event.type == Common::EVENT_KEYDOWN)
+ _vm->_sound->playNote(6177, 1);
+ _vm->_system->delayMillis(1);
+ }
+}
+
+void GhostRoom::doBat() {
+ _batCount++;
+
+ int8 dx = 0;
+ int8 iy = 0;
+ byte batImage = 0;
+ if ((_batCount % 2) == 1) {
+ if ((1 <= _batCount) && (_batCount <= 90)) {
+ dx = 2;
+ iy = 1;
+ batImage = 0;
+ } else if ((91 <= _batCount) && (_batCount <= 240)) {
+ dx = 1;
+ iy = 1;
+ batImage = 1;
+ } else if((241 <= _batCount) && (_batCount <= 260)) {
+ dx = 1;
+ iy = 4;
+ batImage = 2;
+ }
+
+ if ((_batCount == 91) || (_batCount == 241)) // When the bat changes, blank out the old one.
+ _vm->_graphics->drawFilledRectangle(Common::Rect(_batX + _bat[batImage].w, _batY, _batX + _bat[batImage - 1].w, _batY + _bat[batImage - 1].h), kColorBlack);
+
+ _vm->_graphics->drawFilledRectangle(Common::Rect(_batX, _batY, _batX + _bat[batImage].w, _batY + iy), kColorBlack);
+ _vm->_graphics->drawFilledRectangle(Common::Rect(_batX + _bat[batImage].w - dx, _batY, _batX + _bat[batImage].w, _batY + _bat[batImage].h), kColorBlack);
+
+ _batX -= dx;
+ _batY++;
+ _vm->_graphics->ghostDrawPicture(_bat[batImage], _batX, _batY);
+ }
+}
+
+void GhostRoom::bigGreenEyes(byte how) {
+ _vm->_graphics->ghostDrawPicture(_greenEyes[how], 330, 103);
+ _vm->_graphics->ghostDrawPicture(_greenEyes[how], 376, 103);
+ _vm->_graphics->refreshScreen();
+}
+
+ChunkBlock GhostRoom::readChunkBlock(Common::File &file) {
+ ChunkBlock cb;
+ cb._flavour = (Flavour)file.readByte();
+ cb._x = file.readSint16LE();
+ cb._y = file.readSint16LE();
+ cb._width = file.readSint16LE();
+ cb._height = file.readSint16LE();
+ cb._size = file.readSint32LE();
+ return cb;
+}
+
+void GhostRoom::loadPictures() {
+ Common::File file;
+
+ if (!file.open("spooky.avd"))
+ error("AVALANCHE: GhostRoom: File not found: spooky.avd");
+
+ file.seek(44);
+
+ // Initializing ghost's array.
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 2; j++) {
+ for (int y = 0; y < 66; y++) {
+ for (int x = 0; x < 26; x++)
+ _ghost[i][j][y][x] = 0;
+ }
+ }
+ }
+
+ // Read in the pictures of the ghost.
+ for (int i = 0; i < 5; i++) {
+ ChunkBlock cb = readChunkBlock(file);
+ for (int j = 0; j < 2; j++) {
+ for (int y = 0; y <= cb._height; y++)
+ file.read(_ghost[i][j][y], cb._width / 8);
+ }
+ }
+
+ for (int i = 0; i < 2; i++)
+ _eyes[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
+
+ _exclamation = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
+
+ // Actually this function not just loads, but also draws the images, but they are part of the background
+ // and they are need to be drawn only once.
+ _vm->_graphics->ghostDrawBackgroundItems(file);
+
+ for (int i = 0; i < 3; i++)
+ _bat[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
+
+
+ // Initializing glerk's array.
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 4; j++) {
+ for (int y = 0; y < 35; y++) {
+ for (int x = 0; x < 9; x++)
+ _glerk[i][j][y][x] = 0;
+ }
+ }
+ }
+
+ // Read in the pictures of the "glerk".
+ for (int i = 0; i < 6; i++) {
+ ChunkBlock cb = readChunkBlock(file);
+ for (int j = 0; j < 4; j++) {
+ for (int y = 0; y <= cb._height; y++)
+ file.read(_glerk[i][j][y], cb._width / 8);
+ }
+ }
+
+ for (int i = 0; i < 6; i++)
+ _aargh[i] = _vm->_graphics->ghostLoadPicture(file, _aarghWhere[i]);
+
+ for (int i = 0; i < 5; i++)
+ _greenEyes[i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 6; j++)
+ _greldet[j][i] = _vm->_graphics->ghostLoadPicture(file, dummyCoord);
+ }
+
+ file.close();
+}
+
+void GhostRoom::run() {
+ CursorMan.showMouse(false);
+ _vm->_graphics->saveScreen();
+ _vm->fadeOut();
+ _vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlack); // Black out the whole screen.
+ _vm->fadeIn();
+
+ // Only load the pictures if it's our first time walking into the room.
+ // After that we simply use the already loaded images.
+ if (!_wasLoaded) {
+ loadPictures();
+ _wasLoaded = true;
+ }
+
+ // Avvy walks over:
+ _glerkStage = 0;
+ _batX = 277;
+ _batY = 40;
+ _batCount = 0;
+
+ for (int x = 500; x >= 217; x--) {
+ // The floating eyeballs:
+ int xBound = x % 30;
+ if ((22 <= xBound) && (xBound <= 27)) {
+ if (xBound == 27)
+ _vm->_graphics->drawFilledRectangle(Common::Rect(x, 135, x + 17, 137), kColorBlack);
+ _vm->_graphics->ghostDrawPicture(_eyes[0], x, 136);
+ _vm->_graphics->drawDot(x + 16, 137, kColorBlack);
+ } else {
+ if (xBound == 21)
+ _vm->_graphics->drawFilledRectangle(Common::Rect(x, 137, x + 18, 139), kColorBlack);
+ _vm->_graphics->ghostDrawPicture(_eyes[0], x, 135);
+ _vm->_graphics->drawDot(x + 16, 136, kColorBlack); // Eyes would leave a trail 1 pixel high behind them.
+ }
+
+ // Plot the Glerk:
+ if ((x % 10) == 0) {
+ if (_glerkStage > 25)
+ break;
+
+ _vm->_graphics->ghostDrawGlerk(_glerk[kGlerkFade[_glerkStage]], 456, 14);
+ _glerkStage++;
+ }
+
+ doBat();
+
+ _vm->_graphics->refreshScreen();
+
+ wait(15);
+ }
+
+ // Blank out the Glerk's space.
+ _vm->_graphics->drawFilledRectangle(Common::Rect(456, 14, 530, 50), kColorBlack);
+ _vm->_graphics->refreshScreen();
+
+
+ // Here comes the descending ghost:
+ for (int y = -64; y <= 103; y++) {
+ _vm->_graphics->ghostDrawGhost(_ghost[1 + (abs(y / 7) % 2) * 3], 0, y);
+ if (y > 0)
+ _vm->_graphics->drawFilledRectangle(Common::Rect(0, y - 1, 26 * 8, y), kColorBlack);
+ _vm->_graphics->refreshScreen();
+
+ wait(27);
+ }
+
+ // Then it waves:
+ _aarghCount = -15;
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 5; j++) {
+ _vm->_graphics->drawFilledRectangle(Common::Rect(0, 96, 26 * 8, 169), kColorBlack);
+ _vm->_graphics->ghostDrawGhost(_ghost[kWaveOrder[j]], 0, 96 + kAdjustment[j]);
+
+ _aarghCount++;
+
+ if (_aarghCount >= 0) {
+ for (int k = 0; k <= _aarghCount; k++)
+ _vm->_graphics->ghostDrawPicture(_aargh[k], _aarghWhere[k].x, _aarghWhere[k].y);
+ }
+
+ _vm->_graphics->refreshScreen();
+
+ wait(177);
+ }
+ }
+
+ // The exclamation mark appears:
+ _vm->_graphics->ghostDrawPicture(_exclamation, 246, 127);
+ _vm->_graphics->refreshScreen();
+ wait(777);
+
+ // Erase "aargh":
+ _vm->_graphics->drawFilledRectangle(Common::Rect(172, 78, 348, 112), kColorBlack);
+ _vm->_graphics->refreshScreen();
+
+ for (int i = 4; i >= 0; i--) {
+ wait(377);
+ bigGreenEyes(i);
+ }
+
+ // Erase the exclamation mark:
+ _vm->_graphics->drawFilledRectangle(Common::Rect(246, 127, 252, 134), kColorBlack);
+ _vm->_graphics->refreshScreen();
+
+ // Avvy hurries back:
+ _glerkStage = 0;
+ _greldetCount = 18;
+ _redGreldet = false;
+
+ for (int x = 217; x <= 479; x++) {
+ // The floating eyeballs again:
+ int xBound = x % 30;
+ if ((22 <= xBound) && (xBound <= 27)) {
+ if (xBound == 22)
+ _vm->_graphics->drawFilledRectangle(Common::Rect(x + 22, 134, x + 38, 138), kColorBlack);
+ _vm->_graphics->ghostDrawPicture(_eyes[1], x + 23, 136);
+ _vm->_graphics->drawDot(x + 22, 137, kColorBlack);
+ } else {
+ if (xBound == 28)
+ _vm->_graphics->drawFilledRectangle(Common::Rect(x + 22, 135, x + 38, 139), kColorBlack);
+ _vm->_graphics->ghostDrawPicture(_eyes[1], x + 23, 135);
+ _vm->_graphics->drawDot(x + 22, 136, kColorBlack); // Eyes would leave a trail 1 pixel high behind them.
+ }
+
+ // Plot the Green Eyes:
+ if ((x % 53) == 5) {
+ bigGreenEyes(_glerkStage);
+ _glerkStage++;
+ }
+
+ // Plot the Greldet:
+ if (_greldetCount == 18) {
+ _greldetX = _vm->_rnd->getRandomNumber(599);
+ _greldetY = _vm->_rnd->getRandomNumber(79);
+ _greldetCount = 0;
+ _redGreldet = !_redGreldet;
+ }
+
+ _vm->_graphics->ghostDrawPicture(_greldet[kGreldetFade[_greldetCount]][_redGreldet], _greldetX, _greldetY);
+ _greldetCount++;
+
+ _vm->_graphics->refreshScreen();
+
+ wait(10);
+ }
+
+ CursorMan.showMouse(true);
+
+ _vm->fadeOut();
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+ _vm->_animation->animLink();
+ _vm->fadeIn();
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/ghostroom.h b/engines/avalanche/ghostroom.h
new file mode 100644
index 0000000000..b4917d8cb4
--- /dev/null
+++ b/engines/avalanche/ghostroom.h
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+* Copyright (c) 1994-1995 Mike: Mark and Thomas Thurman.
+*/
+
+#ifndef AVALANCHE_GHOSTROOM_H
+#define AVALANCHE_GHOSTROOM_H
+
+#include "common/scummsys.h"
+#include "graphics/surface.h"
+
+namespace Avalanche {
+class AvalancheEngine;
+
+struct ChunkBlock {
+ Flavour _flavour;
+ int16 _x, _y;
+ int16 _width, _height;
+ int32 _size;
+};
+
+class GhostRoom {
+public:
+ GhostRoom(AvalancheEngine *vm);
+ ~GhostRoom();
+
+ void run();
+ ChunkBlock readChunkBlock(Common::File &file);
+
+private:
+ AvalancheEngine *_vm;
+
+ static const int8 kAdjustment[5];
+ static const byte kWaveOrder[5];
+ static const byte kGlerkFade[26];
+ static const byte kGreldetFade[18];
+
+ Common::Point dummyCoord;
+ byte _ghost[5][2][66][26];
+ Graphics::Surface _eyes[2];
+ Graphics::Surface _exclamation;
+ Graphics::Surface _bat[3];
+ byte _glerk[6][4][35][9];
+ Graphics::Surface _aargh[6];
+ Common::Point _aarghWhere[6];
+ Graphics::Surface _greenEyes[5];
+ Graphics::Surface _greldet[6][2];
+
+ int16 _batX, _batY;
+ uint16 _batCount;
+ byte _glerkStage;
+ int8 _aarghCount;
+ int16 _greldetX, _greldetY;
+ byte _greldetCount;
+ bool _redGreldet;
+ bool _wasLoaded;
+
+ void loadPictures();
+ void wait(uint16 howLong);
+ void doBat();
+ void bigGreenEyes(byte how);
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_GHOSTROOM_H
diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp
index a8efc4be9b..a1087375b2 100644
--- a/engines/avalanche/graphics.cpp
+++ b/engines/avalanche/graphics.cpp
@@ -281,6 +281,10 @@ Common::Point GraphicManager::drawArc(Graphics::Surface &surface, int16 x, int16
return endPoint;
}
+void GraphicManager::drawDot(int x, int y, Color color) {
+ *(byte *)_surface.getBasePtr(x, y) = color;
+}
+
void GraphicManager::drawLine(int x1, int y1, int x2, int y2, int penX, int penY, Color color) {
_surface.drawThickLine(x1, y1, x2, y2, penX, penY, color);
}
@@ -348,6 +352,25 @@ void GraphicManager::drawNormalText(const Common::String text, FontType font, by
drawText(_surface, text, font, fontHeight, x, y, color);
}
+/**
+ * Used in Help. Draws text double the size of the normal.
+ */
+void GraphicManager::drawBigText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) {
+ for (uint i = 0; i < text.size(); i++) {
+ for (int j = 0; j < fontHeight; j++) {
+ byte pixel = font[(byte)text[i]][j];
+ byte pixelBit = 0;
+ for (int bit = 0; bit < 16; bit++) {
+ if ((bit % 2) == 0)
+ pixelBit = (pixel >> (bit / 2)) & 1;
+ for (int k = 0; k < 2; k++)
+ if (pixelBit)
+ *(byte *)_surface.getBasePtr(x + i * 16 + 16 - bit, y + j * 2 + k) = color;
+ }
+ }
+ }
+}
+
void GraphicManager::drawScrollText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color) {
drawText(_scrolls, text, font, fontHeight, x, y, color);
}
@@ -500,6 +523,213 @@ void GraphicManager::nimFree() {
_nimLogo.free();
}
+void GraphicManager::ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY) {
+ const byte kPlaneToUse[4] = { 0, 0, 0, 1 };
+ // Constants from the original code:
+ uint16 height = 66;
+ const uint16 width = 26 * 8;
+
+ // We have to mess around with the coords and the sizes since
+ // the ghost isn't always placed fully on the screen.
+ int yStart = 0;
+ if (destY < 0) {
+ yStart = abs(destY);
+ height -= yStart;
+ destY = 0;
+ }
+
+ Graphics::Surface ghostPic;
+ ghostPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int y = 0; y < height; y++) {
+ for (int plane = 0; plane < 4; plane++) {
+ for (uint16 x = 0; x < width / 8; x ++) {
+ byte pixel = ghostArr[kPlaneToUse[plane]][y + yStart][x];
+ for (int bit = 0; bit < 8; bit++) {
+ byte pixelBit = (pixel >> bit) & 1;
+ *(byte *)ghostPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane);
+ }
+ }
+ }
+ }
+
+ drawPicture(_surface, ghostPic, destX, destY);
+
+ ghostPic.free();
+}
+
+void GraphicManager::ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY) {
+ // Constants from the original code:
+ const uint16 height = 35;
+ const uint16 width = 9 * 8;
+
+ Graphics::Surface glerkPic;
+ glerkPic.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int y = 0; y < height; y++) {
+ for (int plane = 0; plane < 4; plane++) {
+ for (uint16 x = 0; x < width / 8; x++) {
+ byte pixel = glerkArr[plane][y][x];
+ for (int bit = 0; bit < 8; bit++) {
+ byte pixelBit = (pixel >> bit) & 1;
+ *(byte *)glerkPic.getBasePtr(x * 8 + 7 - bit, y) += (pixelBit << plane);
+ }
+ }
+ }
+ }
+
+ drawPicture(_surface, glerkPic, destX, destY);
+
+ glerkPic.free();
+}
+
+/**
+ * With the use of the second argument, it replaces get_meg_aargh as well.
+ * @remarks Originally called 'get_me' and was located in Ghostroom.
+ */
+Graphics::Surface GraphicManager::ghostLoadPicture(Common::File &file, Common::Point &coord) {
+ ChunkBlock cb = _vm->_ghostroom->readChunkBlock(file);
+
+ coord.x = cb._x;
+ coord.y = cb._y;
+
+ Graphics::Surface picture = loadPictureGraphic(file);
+
+ int bytesPerRow = (picture.w / 8);
+ if ((picture.w % 8) > 0)
+ bytesPerRow += 1;
+ int loadedBytes = picture.h * bytesPerRow * 4 + 4;
+ // * 4 is for the four planes, + 4 is for the reading of the width and the height at loadPictureGraphic's beginning.
+
+ int bytesToSkip = cb._size - loadedBytes;
+ file.skip(bytesToSkip);
+
+ return picture;
+}
+
+void GraphicManager::ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY) {
+ drawPicture(_surface, picture, destX, destY);
+}
+
+/**
+ * Loads and puts 3 images (in this order: cobweb, Mark's signature, open door) into the background at the beginning of the ghostroom scene.
+ * @remarks Originally called 'plain_grab' and was located in Ghostroom. It was originally called 3 times. I unified these in one function, used a for cycle.
+ */
+void GraphicManager::ghostDrawBackgroundItems(Common::File &file) {
+ for (int num = 0; num < 3; num++) {
+ ChunkBlock cb = _vm->_ghostroom->readChunkBlock(file);
+
+ int width = cb._width;
+ int height = cb._height + 1;
+
+ Graphics::Surface picture;
+ picture.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ // Load the picture according to it's type.
+ switch (cb._flavour) {
+ case kFlavourOne: // There is only one plane.
+ for (uint16 y = 0; y < height; y++) {
+ for (uint16 x = 0; x < width; x += 8) {
+ byte pixel = file.readByte();
+ for (int i = 0; i < 8; i++) {
+ byte pixelBit = (pixel >> i) & 1;
+ *(byte *)picture.getBasePtr(x + 7 - i, y) = (pixelBit << 3);
+ }
+ }
+ }
+ break;
+ case kFlavourEga:
+ picture = loadPictureRaw(file, width, height);
+ break;
+ default:
+ break;
+ }
+
+ drawPicture(_surface, picture, cb._x, cb._y);
+
+ picture.free();
+ }
+ refreshScreen();
+}
+
+/**
+* @remarks Originally called 'plot_button'
+*/
+void GraphicManager::helpDrawButton(int y, byte which) {
+ if (y > 200) {
+ _vm->_graphics->setBackgroundColor(kColorGreen);
+ _vm->_system->delayMillis(10);
+ _vm->_graphics->setBackgroundColor(kColorBlack);
+ return;
+ }
+
+ Common::File file;
+
+ if (!file.open("buttons.avd"))
+ error("AVALANCHE: Help: File not found: buttons.avd");
+
+ file.seek(which * 930); // 930 is the size of one button.
+
+ Graphics::Surface button = loadPictureGraphic(file);
+
+ int x = 0;
+ if (y == -177) {
+ x = 229;
+ y = 5;
+ }
+ else
+ x = 470;
+
+ _vm->_graphics->drawPicture(_surface, button, x, y);
+
+ button.free();
+ file.close();
+}
+
+/**
+ * @remarks Originally called 'light'
+ */
+void GraphicManager::helpDrawHighlight(byte which, Color color) {
+ if (which == 177) // Dummy value for "no button at all".
+ return;
+
+ which &= 31;
+ drawRectangle(Common::Rect(466, 38 + which * 27, 555, 63 + which * 27), color);
+}
+
+/**
+ * @remarks Originally called 'titles'
+ */
+void GraphicManager::seuDrawTitle() {
+ Common::File file;
+
+ if (!file.open("shoot1.avd"))
+ error("AVALANCHE: ShootEmUp: File not found: shoot1.avd");
+
+ const uint16 width = 320;
+ const uint16 height = 200;
+
+ Graphics::Surface picture = loadPictureRaw(file, width, height);
+
+ Graphics::Surface doubledPicture;
+ doubledPicture.create(width * 2, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ // These cycles are for doubling the picture's width.
+ for (int x = (width * 2) - 2 ; x >= 0; x -= 2) {
+ for (int y = 0; y < height; y++) {
+ *(byte *)doubledPicture.getBasePtr(x, y) = *(byte *)doubledPicture.getBasePtr(x + 1, y) = *(byte *)picture.getBasePtr(x / 2, y);
+ }
+ }
+
+ drawPicture(_surface, doubledPicture, 0, 0);
+ refreshScreen();
+
+ picture.free();
+ doubledPicture.free();
+
+ file.close();
+}
+
/**
* This function mimics Pascal's getimage().
*/
@@ -510,7 +740,7 @@ Graphics::Surface GraphicManager::loadPictureGraphic(Common::File &file) {
Graphics::Surface picture; // We make a Surface object for the picture itself.
picture.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-
+
// Produce the picture. We read it in row-by-row, and every row has 4 planes.
for (int y = 0; y < height; y++) {
for (int8 plane = 3; plane >= 0; plane--) { // The planes are in the opposite way.
@@ -518,8 +748,7 @@ Graphics::Surface GraphicManager::loadPictureGraphic(Common::File &file) {
byte pixel = file.readByte();
for (int bit = 0; bit < 8; bit++) {
byte pixelBit = (pixel >> bit) & 1;
- if (pixelBit != 0)
- *(byte *)picture.getBasePtr(x + 7 - bit, y) += (pixelBit << plane);
+ *(byte *)picture.getBasePtr(x + 7 - bit, y) += (pixelBit << plane);
}
}
}
@@ -567,8 +796,7 @@ Graphics::Surface GraphicManager::loadPictureSign(Common::File &file, int xl, in
byte pixel = file.readByte();
for (int bit = 0; bit < 8; bit++) {
byte pixelBit = (pixel >> bit) & 1;
- if (pixelBit != 0)
- *(byte *)picture.getBasePtr(xx + 7 - bit, yy) += (pixelBit << plane);
+ *(byte *)picture.getBasePtr(xx + 7 - bit, yy) += (pixelBit << plane);
}
}
}
@@ -587,6 +815,19 @@ void GraphicManager::shiftScreen() {
_surface.drawLine(0, 0, _surface.w, 0, kColorBlack);
}
+void GraphicManager::drawWinningPic() {
+ Common::File file;
+
+ if (!file.open("finale.avd"))
+ error("AVALANCHE: Timer: File not found: finale.avd");
+
+ Graphics::Surface winning = loadPictureRaw(file, 640, 200);
+ drawPicture(_surface, winning, 0, 0);
+
+ winning.free();
+ file.close();
+}
+
void GraphicManager::clearAlso() {
_magics.fillRect(Common::Rect(0, 0, 640, 200), 0);
_magics.frameRect(Common::Rect(0, 45, 640, 161), 15);
@@ -799,10 +1040,10 @@ void GraphicManager::showScroll() {
void GraphicManager::getNaturalPicture(SpriteType &sprite) {
sprite._type = kNaturalImage; // We simply read from the screen and later, in drawSprite() we draw it right back.
- sprite._size = sprite._xl * 8 * sprite._yl + 1;
- sprite._picture.create(sprite._xl * 8, sprite._yl + 1, Graphics::PixelFormat::createFormatCLUT8());
- for (uint16 y = 0; y < sprite._yl + 1; y++) {
- for (uint16 x = 0; x < sprite._xl * 8; x++)
+ sprite._size = sprite._width * 8 * sprite._height + 1;
+ sprite._picture.create(sprite._width * 8, sprite._height + 1, Graphics::PixelFormat::createFormatCLUT8());
+ for (uint16 y = 0; y < sprite._height + 1; y++) {
+ for (uint16 x = 0; x < sprite._width * 8; x++)
*(byte *)sprite._picture.getBasePtr(x, y) = *(byte *)_vm->_graphics->_surface.getBasePtr(sprite._x * 8 + x, sprite._y + y);
}
}
diff --git a/engines/avalanche/graphics.h b/engines/avalanche/graphics.h
index 636ae6fdf9..536a2c2f1a 100644
--- a/engines/avalanche/graphics.h
+++ b/engines/avalanche/graphics.h
@@ -38,6 +38,7 @@ namespace Avalanche {
class AvalancheEngine;
class AnimationType;
struct SpriteType;
+struct ChunkBlock;
typedef byte FontType[256][16];
typedef byte ManiType[2049];
@@ -58,11 +59,15 @@ public:
void loadDigits();
void loadMouse(byte which);
+ void drawDot(int x, int y, Color color);
void drawLine(int x1, int y1, int x2, int y2, int penX, int penY, Color color);
Common::Point drawScreenArc(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
void drawPieSlice(int16 x, int16 y, int16 stAngle, int16 endAngle, uint16 radius, Color color);
void drawTriangle(Common::Point *p, Color color);
+ void drawFilledRectangle(Common::Rect rect, Color color);
+ void drawRectangle(Common::Rect rect, Color color);
void drawNormalText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
+ void drawBigText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color); // Very similar to drawText. TODO: Try to unify the two.
void drawScrollText(const Common::String text, FontType font, byte fontHeight, int16 x, int16 y, Color color);
void drawDigit(int index, int x, int y);
void drawDirection(int index, int x, int y);
@@ -79,8 +84,6 @@ public:
void drawDebugLines();
// For the mini-game "Nim".
- void drawFilledRectangle(Common::Rect rect, Color color);
- void drawRectangle(Common::Rect rect, Color color);
void nimLoad();
void nimDrawStone(int x, int y);
void nimDrawInitials();
@@ -90,6 +93,23 @@ public:
// Used in wobble()
void shiftScreen();
+ // Used in winning()
+ void drawWinningPic();
+
+ // Ghostroom's functions:
+ void ghostDrawGhost(byte ghostArr[2][66][26], uint16 destX, int16 destY); // Very similar to loadPictureSign(). TODO: Unify the two later if possible.
+ void ghostDrawGlerk(byte glerkArr[4][35][9], uint16 destX, uint16 destY); // Very similar to ghostDrawGhost(), but not enough to unify the two.
+ Graphics::Surface ghostLoadPicture(Common::File &file, Common::Point &coord);
+ void ghostDrawPicture(const Graphics::Surface &picture, uint16 destX, uint16 destY);
+ void ghostDrawBackgroundItems(Common::File &file);
+
+ // Help's function:
+ void helpDrawButton(int y, byte which);
+ void helpDrawHighlight(byte which, Color color);
+
+ // Shoot em' up's functions:
+ void seuDrawTitle();
+
void clearAlso();
void clearTextBar();
void setAlsoLine(int x1, int y1, int x2, int y2, Color color);
diff --git a/engines/avalanche/help.cpp b/engines/avalanche/help.cpp
new file mode 100644
index 0000000000..0d4eff9c23
--- /dev/null
+++ b/engines/avalanche/help.cpp
@@ -0,0 +1,268 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+*/
+
+/* Original name: HELPER The help system unit. */
+
+#include "avalanche/avalanche.h"
+#include "avalanche/help.h"
+
+#include "common/scummsys.h"
+
+namespace Avalanche {
+
+Help::Help(AvalancheEngine *vm) {
+ _vm = vm;
+
+ for (int i = 0; i < 10; i++) {
+ _buttons[i]._trigger = Common::KEYCODE_INVALID;
+ _buttons[i]._whither = 0;
+ }
+ _highlightWas = 0;
+ _buttonNum = 0;
+ _holdLeft = false;
+}
+
+/**
+ * Loads and draws the chosen page of the help.
+ * @remarks Originally called 'getme'
+ */
+void Help::switchPage(byte which) {
+ // Help icons are 80x20.
+
+ _highlightWas = 177; // Forget where the highlight was.
+
+ Common::File file;
+
+ if (!file.open("help.avd"))
+ error("AVALANCHE: Help: File not found: help.avd");
+
+ file.seek(which * 2);
+ uint16 offset = file.readUint16LE();
+ file.seek(offset);
+
+ Common::String title = getLine(file);
+
+ _vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlue);
+ _vm->_graphics->drawFilledRectangle(Common::Rect(8, 40, 450, 200), kColorWhite);
+
+ byte index = file.readByte();
+ _vm->_graphics->helpDrawButton(-177, index);
+
+ // Plot the title:
+ _vm->_graphics->drawNormalText(title, _vm->_font, 8, 629 - 8 * title.size(), 26, kColorBlack);
+ _vm->_graphics->drawNormalText(title, _vm->_font, 8, 630 - 8 * title.size(), 25, kColorCyan);
+
+ _vm->_graphics->drawBigText("help!", _vm->_font, 8, 549, 1, kColorBlack);
+ _vm->_graphics->drawBigText("help!", _vm->_font, 8, 550, 0, kColorCyan);
+
+ byte y = 0;
+ do {
+ Common::String line = getLine(file);
+ if (!line.empty()) {
+ if (line.compareTo(Common::String('!')) == 0) // End of the help text is signalled with a '!'.
+ break;
+ if (line[0] == '\\') {
+ line.deleteChar(0);
+ _vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorRed);
+ }
+ else
+ _vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorBlack);
+ }
+ y++;
+ } while (true);
+
+ // We are now at the end of the text. Next we must read the icons:
+ y = 0;
+ _buttonNum = 0;
+ while (!file.eos()) {
+ int trigger = file.readByte();
+
+ if (trigger == 177)
+ break;
+ switch (trigger) {
+ case 254: // Escape
+ trigger = 27;
+ break;
+ case 214: // PageUp
+ trigger = 280;
+ break;
+ case 216: // PageDown
+ trigger = 281;
+ break;
+ default: // A - Z
+ // The characters are stored in the file in uppercase, but we need the lowercase versions for KeyCode:
+ trigger = tolower(trigger);
+ break;
+ }
+
+ _buttons[y]._trigger = Common::KeyCode(trigger);
+ index = file.readByte();
+ if (_buttons[y]._trigger != Common::KEYCODE_INVALID)
+ _vm->_graphics->helpDrawButton(13 + (y + 1) * 27, index);
+ _buttons[y]._whither = file.readByte(); // This is the position to jump to.
+
+ Common::String text = "";
+ switch (_buttons[y]._trigger) {
+ case Common::KEYCODE_ESCAPE:
+ text = Common::String("Esc");
+ break;
+ case Common::KEYCODE_PAGEUP:
+ text = Common::String(24);
+ break;
+ case Common::KEYCODE_PAGEDOWN:
+ text = Common::String(25);
+ break;
+ default:
+ text = Common::String(toupper(_buttons[y]._trigger));
+ break;
+ }
+
+ _vm->_graphics->drawBigText(text, _vm->_font, 8, 589 - (text.size() * 8), 18 + (y + 1) * 27, kColorBlack);
+ _vm->_graphics->drawBigText(text, _vm->_font, 8, 590 - (text.size() * 8), 17 + (y + 1) * 27, kColorCyan);
+
+ y++;
+ _buttonNum++;
+ }
+
+ _vm->_graphics->refreshScreen();
+
+ file.close();
+}
+
+Common::String Help::getLine(Common::File &file) {
+ Common::String line;
+ byte length = file.readByte();
+ for (int i = 0; i < length; i++) {
+ char c = file.readByte();
+ line += (c ^ 177);
+ }
+ return line;
+}
+
+bool Help::handleMouse(const Common::Event &event) {
+ Common::Point mousePos;
+ mousePos.x = event.mouse.x;
+ mousePos.y = event.mouse.y / 2;
+
+ int index = -1;
+
+ if (event.type == Common::EVENT_LBUTTONUP) { // Clicked *somewhere*...
+ _holdLeft = false;
+
+ if ((mousePos.x < 470) || (mousePos.x > 550) || (((mousePos.y - 13) % 27) > 20))
+ index = -1;
+ else // Clicked on a button.
+ index = ((mousePos.y - 13) / 27) - 1;
+ } else { // LBUTTONDOWN or MOUSEMOVE
+ int highlightIs = 0;
+
+ if ((mousePos.x > 470) && (mousePos.x <= 550) && (((mousePos.y - 13) % 27) <= 20)) { // No click, so highlight.
+ highlightIs = (mousePos.y - 13) / 27 - 1;
+ if ((highlightIs < 0) || (5 < highlightIs))
+ highlightIs = 177; // In case of silly values.
+ } else
+ highlightIs = 177;
+
+ if (((highlightIs != 177) && (event.type == Common::EVENT_LBUTTONDOWN)) || _holdLeft) {
+ _holdLeft = true;
+ highlightIs += 32;
+ }
+
+ if (_highlightWas != highlightIs) {
+ _vm->_graphics->helpDrawHighlight(_highlightWas, kColorBlue);
+ _highlightWas = highlightIs;
+ if (_buttons[highlightIs & 31]._trigger != Common::KEYCODE_INVALID) {
+ if (highlightIs > 31)
+ _vm->_graphics->helpDrawHighlight(highlightIs, kColorLightcyan);
+ else
+ _vm->_graphics->helpDrawHighlight(highlightIs, kColorLightblue);
+ }
+ }
+ }
+
+ if ((index >= 0) && (_buttons[index]._trigger != Common::KEYCODE_INVALID)) {
+ if (_buttons[index]._trigger == Common::KEYCODE_ESCAPE)
+ return true;
+ else {
+ _vm->fadeOut();
+ switchPage(_buttons[index]._whither);
+ _vm->fadeIn();
+ return false;
+ }
+ }
+
+ return false;
+}
+
+bool Help::handleKeyboard(const Common::Event &event) {
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
+ return true;
+
+ for (int i = 0; i < _buttonNum; i++) {
+ if (_buttons[i]._trigger == event.kbd.keycode) {
+ _vm->fadeOut();
+ switchPage(_buttons[i]._whither);
+ _vm->fadeIn();
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * @remarks Originally called 'boot_help'
+ */
+void Help::run() {
+ _vm->_graphics->saveScreen();
+ _vm->fadeOut();
+ switchPage(0);
+ _vm->fadeIn();
+
+ _vm->_graphics->loadMouse(kCurHelp);
+
+ // Originally it was the body of 'continue_help':
+ bool close = false;
+ while (!_vm->shouldQuit() && !close) {
+ Common::Event event;
+ _vm->getEvent(event);
+ if (event.type == Common::EVENT_KEYDOWN)
+ close = handleKeyboard(event);
+ else if ((event.type == Common::EVENT_LBUTTONDOWN) || (event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_MOUSEMOVE))
+ close = handleMouse(event);
+
+ _vm->_graphics->refreshScreen();
+ }
+ // End of 'continue_help'.
+
+ _vm->fadeOut();
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+ _vm->fadeIn();
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/help.h b/engines/avalanche/help.h
new file mode 100644
index 0000000000..f31a73d189
--- /dev/null
+++ b/engines/avalanche/help.h
@@ -0,0 +1,65 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+*/
+
+/* Original name: HELPER The help system unit. */
+
+#ifndef AVALANCHE_HELP_H
+#define AVALANCHE_HELP_H
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class Help {
+public:
+ Help(AvalancheEngine *vm);
+
+ void run();
+
+private:
+ struct Button {
+ Common::KeyCode _trigger;
+ byte _whither;
+ };
+
+ AvalancheEngine *_vm;
+
+ Button _buttons[10];
+ byte _highlightWas;
+ byte _buttonNum; // How many buttons do we have on the screen at the moment?
+ bool _holdLeft; // Is the left mouse button is still being held?
+
+ void switchPage(byte which);
+ Common::String getLine(Common::File &file); // It was a nested function in getMe().
+
+ // These two return true if we have to leave the Help:
+ bool handleMouse(const Common::Event &event);
+ bool handleKeyboard(const Common::Event &event);
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_HELP_H
diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk
index 39ca94e3f8..eb95e32585 100644
--- a/engines/avalanche/module.mk
+++ b/engines/avalanche/module.mk
@@ -11,13 +11,15 @@ MODULE_OBJS = \
graphics.o \
menu.o \
parser.o \
- pingo.o \
dialogs.o \
sequence.o \
sound.o \
timer.o \
nim.o \
- clock.o
+ clock.o \
+ ghostroom.o \
+ help.o \
+ shootemup.o
# This module can be built as a plugin
ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN)
diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp
index b0524a0d7e..1a9585e2a3 100644
--- a/engines/avalanche/parser.cpp
+++ b/engines/avalanche/parser.cpp
@@ -2043,8 +2043,7 @@ void Parser::doThat() {
}
break;
case kVerbCodeHelp:
- // boot_help();
- warning("STUB: Parser::doThat() - case kVerbCodehelp");
+ _vm->_help->run();
break;
case kVerbCodeLarrypass:
_vm->_dialogs->displayText("Wrong game!");
diff --git a/engines/avalanche/pingo.cpp b/engines/avalanche/pingo.cpp
deleted file mode 100644
index 40467ab839..0000000000
--- a/engines/avalanche/pingo.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/*
- * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
- * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
- */
-
-/* PINGO Full-screen sub-parts of the game. */
-
-#include "avalanche/avalanche.h"
-#include "avalanche/pingo.h"
-
-namespace Avalanche {
-
-Pingo::Pingo(AvalancheEngine *vm) {
- _vm = vm;
-}
-
-void Pingo::dPlot(int16 x, int16 y, Common::String z) {
- warning("STUB: Pingo::dPlot()");
-}
-
-void Pingo::bossKey() {
- warning("STUB: Pingo::bossKey()");
-}
-
-void Pingo::copy02() { // taken from Wobble (below)
- warning("STUB: Pingo::copy02()");
-}
-
-void Pingo::copy03() { // taken from Wobble (below)
- warning("STUB: Pingo::copy03()");
-}
-
-void Pingo::copyPage(byte frp, byte top) { // taken from Copy02 (above)
- warning("STUB: Pingo::copyPage()");
-}
-
-void Pingo::winningPic() {
- Common::File f;
- _vm->fadeOut();
-
- if (!f.open("finale.avd"))
- error("AVALANCHE: File not found: finale.avd");
-
-#if 0
- for (int bit = 0; bit <= 3; bit++) {
- port[0x3c4] = 2;
- port[0x3ce] = 4;
- port[0x3c5] = 1 << bit;
- port[0x3cf] = bit;
- blockread(f, mem[0xa000 * 0], 16000);
- }
-#endif
-
- f.close();
-
- warning("STUB: Pingo::winningPic()");
-
- _vm->fadeIn();
-
-#if 0
- do {
- _vm->check();
- } while (!(keypressed() || (mrelease > 0)));
- while (keypressed())
- char r = readkey();
- major_redraw();
-#endif
-
- warning("STUB: Pingo::winningPic()");
-}
-
-} // End of namespace Avalanche.
diff --git a/engines/avalanche/shootemup.cpp b/engines/avalanche/shootemup.cpp
new file mode 100644
index 0000000000..c9d089c23b
--- /dev/null
+++ b/engines/avalanche/shootemup.cpp
@@ -0,0 +1,175 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+*/
+
+#include "avalanche/avalanche.h"
+#include "avalanche/shootemup.h"
+
+#include "common/random.h"
+
+namespace Avalanche {
+
+ShootEmUp::ShootEmUp(AvalancheEngine *vm) {
+ _vm = vm;
+
+ _time = 0;
+}
+
+void ShootEmUp::run() {
+ _vm->_graphics->seuDrawTitle();
+ setup();
+ initRunner(20, 70, 48, 54, _vm->_rnd->getRandomNumber(4) + 1, _vm->_rnd->getRandomNumber(3) - 2);
+ initRunner(600, 70, 48, 54, _vm->_rnd->getRandomNumber(4) + 1, _vm->_rnd->getRandomNumber(3) - 2);
+ initRunner(600, 100, 61, 67, -(_vm->_rnd->getRandomNumber(4)) + 1, _vm->_rnd->getRandomNumber(3) - 2);
+ initRunner(20, 100, 61, 67, -(_vm->_rnd->getRandomNumber(4)) + 1, _vm->_rnd->getRandomNumber(3) - 2);
+ do {
+ blankIt();
+ hitPeople();
+ plotThem();
+ moveThem();
+ moveAvvy();
+ bumpFolk();
+ peopleRunning();
+ animate();
+ escapeCheck();
+ collisionCheck();
+ updateTime();
+ check321();
+ readKbd();
+ } while (_time != 0);
+}
+
+bool ShootEmUp::overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y) {
+ warning("STUB: ShootEmUp::overlap()");
+ return false;
+}
+
+byte ShootEmUp::getStockNumber(byte x) {
+ warning("STUB: ShootEmUp::getStockNumber()");
+ return 0;
+}
+
+void ShootEmUp::blankIt() {
+ warning("STUB: ShootEmUp::blankIt()");
+}
+
+void ShootEmUp::moveThem() {
+ warning("STUB: ShootEmUp::moveThem()");
+}
+
+void ShootEmUp::plotThem() {
+ warning("STUB: ShootEmUp::plotThem()");
+}
+
+void ShootEmUp::define(int16 xx, int16 yy, byte pp, int8 ixx, int8 iyy, int16 time, bool isAMissile, bool doWeWipe) {
+ warning("STUB: ShootEmUp::define()");
+}
+
+void ShootEmUp::defineCameo(int16 xx, int16 yy, byte pp, int16 time) {
+ warning("STUB: ShootEmUp::defineCameo()");
+}
+
+void ShootEmUp::showStock(byte x) {
+ warning("STUB: ShootEmUp::showStock()");
+}
+
+void ShootEmUp::showScore() {
+ warning("STUB: ShootEmUp::showScore()");
+}
+
+void ShootEmUp::showTime() {
+ warning("STUB: ShootEmUp::showTime()");
+}
+
+void ShootEmUp::gain(int8 howMuch) {
+ warning("STUB: ShootEmUp::gain()");
+}
+
+void ShootEmUp::newEscape() {
+ warning("STUB: ShootEmUp::newEscape()");
+}
+
+void ShootEmUp::nextPage() {
+ warning("STUB: ShootEmUp::nextPage()");
+}
+
+void ShootEmUp::instructions() {
+ warning("STUB: ShootEmUp::instructions()");
+}
+
+void ShootEmUp::setup() {
+ warning("STUB: ShootEmUp::setup()");
+}
+
+void ShootEmUp::initRunner(int16 xx, int16 yy, byte f1, byte f2, int8 ixx, int8 iyy) {
+ warning("STUB: ShootEmUp::initRunner()");
+}
+
+void ShootEmUp::moveAvvy() {
+ warning("STUB: ShootEmUp::moveAvvy()");
+}
+
+void ShootEmUp::readKbd() {
+ warning("STUB: ShootEmUp::readKbd()");
+}
+
+void ShootEmUp::animate() {
+ warning("STUB: ShootEmUp::animate()");
+}
+
+void ShootEmUp::collisionCheck() {
+ warning("STUB: ShootEmUp::collisionCheck()");
+}
+
+void ShootEmUp::turnAround(byte who, bool randomX) {
+ warning("STUB: ShootEmUp::turnAround()");
+}
+
+void ShootEmUp::bumpFolk() {
+ warning("STUB: ShootEmUp::bumpFolk()");
+}
+
+void ShootEmUp::peopleRunning() {
+ warning("STUB: ShootEmUp::peopleRunning()");
+}
+
+void ShootEmUp::updateTime() {
+ warning("STUB: ShootEmUp::updateTime()");
+}
+
+void ShootEmUp::hitPeople() {
+ warning("STUB: ShootEmUp::hitPeople()");
+}
+
+void ShootEmUp::escapeCheck() {
+ warning("STUB: ShootEmUp::escapeCheck()");
+}
+
+void ShootEmUp::check321() {
+ warning("STUB: ShootEmUp::check321()");
+}
+
+} // End of namespace Avalanche
diff --git a/engines/avalanche/shootemup.h b/engines/avalanche/shootemup.h
new file mode 100644
index 0000000000..db1f113817
--- /dev/null
+++ b/engines/avalanche/shootemup.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* This code is based on the original source code of Lord Avalot d'Argent version 1.3.
+* Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
+*/
+
+#ifndef AVALANCHE_SHOOTEMUP_H
+#define AVALANCHE_SHOOTEMUP_H
+
+namespace Avalanche {
+class AvalancheEngine;
+
+class ShootEmUp {
+public:
+ ShootEmUp(AvalancheEngine *vm);
+
+ void run();
+
+private:
+ AvalancheEngine *_vm;
+
+ byte _time;
+
+ bool overlap(uint16 a1x, uint16 a1y, uint16 a2x, uint16 a2y, uint16 b1x, uint16 b1y, uint16 b2x, uint16 b2y);
+ byte getStockNumber(byte x);
+ void blankIt();
+ void moveThem();
+ void plotThem();
+ void define(int16 xx, int16 yy, byte pp, int8 ixx, int8 iyy, int16 time, bool isAMissile, bool doWeWipe);
+ void defineCameo(int16 xx, int16 yy, byte pp, int16 time);
+ void showStock(byte x);
+ void showScore();
+ void showTime();
+ void gain(int8 howMuch);
+ void newEscape();
+ void nextPage(); // Internal function of 'instructions' in the original.
+ void instructions();
+ void setup();
+ void initRunner(int16 xx, int16 yy, byte f1, byte f2, int8 ixx, int8 iyy);
+ void moveAvvy();
+ void readKbd();
+ void animate();
+ void collisionCheck();
+ void turnAround(byte who, bool randomX);
+ void bumpFolk();
+ void peopleRunning();
+ void updateTime();
+ void hitPeople();
+ void escapeCheck();
+ void check321();
+};
+
+} // End of namespace Avalanche
+
+#endif // AVALANCHE_SHOOTEMUP_H
diff --git a/engines/avalanche/timer.cpp b/engines/avalanche/timer.cpp
index c8ea820c0e..b7a8433e71 100644
--- a/engines/avalanche/timer.cpp
+++ b/engines/avalanche/timer.cpp
@@ -327,12 +327,11 @@ void Timer::hangAround2() {
_vm->_animation->_sprites[0]->remove();
spr->remove(); // Get rid of Robin Hood and Friar Tuck.
- addTimer(1, kProcAfterTheShootemup, kReasonHangingAround);
- // Immediately call the following proc (when you have a chance).
+ addTimer(1, kProcAfterTheShootemup, kReasonHangingAround); // Immediately call the following proc (when you have a chance).
_vm->_tiedUp = false;
- // _vm->_enid->backToBootstrap(1); Call the shoot-'em-up. TODO: Replace it with proper ScummVM-friendly function(s)! Do not remove until then!
+ _vm->_shootemup->run();
}
void Timer::afterTheShootemup() {
@@ -632,17 +631,39 @@ void Timer::arkataShouts() {
addTimer(160, kProcArkataShouts, kReasonArkataShouts);
}
+/**
+ * @remarks Contains the content of the function 'winning_pic', originally located in PINGO.
+ */
void Timer::winning() {
_vm->_dialogs->displayScrollChain('Q', 79);
- _vm->_pingo->winningPic();
- warning("STUB: Timer::winning()");
-#if 0
- do {
- _vm->checkclick();
- } while (!(_vm->mrelease == 0));
-#endif
- // TODO: To be implemented with Pingo::winningPic().
+ // This was originally located in winning_pic:
+ CursorMan.showMouse(false);
+ _vm->_graphics->saveScreen();
+ _vm->fadeOut();
+ _vm->_graphics->drawWinningPic();
+ _vm->_graphics->refreshScreen();
+ _vm->fadeIn();
+
+ // Waiting for a keypress or a left mouseclick:
+ Common::Event event;
+ bool escape = false;
+ while (!_vm->shouldQuit() && !escape) {
+ _vm->_graphics->refreshScreen();
+ while (_vm->getEvent(event)) {
+ if ((event.type == Common::EVENT_LBUTTONUP) || (event.type == Common::EVENT_KEYDOWN)) {
+ escape = true;
+ break;
+ }
+ }
+ }
+
+ _vm->fadeOut();
+ _vm->_graphics->restoreScreen();
+ _vm->_graphics->removeBackup();
+ _vm->fadeIn();
+ CursorMan.showMouse(true);
+ // winning_pic's end.
_vm->callVerb(kVerbCodeScore);
_vm->_dialogs->displayText(" T H E E N D ");
diff --git a/engines/cge/cge_main.cpp b/engines/cge/cge_main.cpp
index 602b36d6ef..b4015334c8 100644
--- a/engines/cge/cge_main.cpp
+++ b/engines/cge/cge_main.cpp
@@ -125,9 +125,8 @@ char *CGEEngine::mergeExt(char *buf, const char *name, const char *ext) {
}
int CGEEngine::takeEnum(const char **tab, const char *text) {
- const char **e;
if (text) {
- for (e = tab; *e; e++) {
+ for (const char **e = tab; *e; e++) {
if (scumm_stricmp(text, *e) == 0) {
return e - tab;
}
@@ -1029,7 +1028,6 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i
bool east = false;
bool port = false;
bool tran = false;
- int i, lcnt = 0;
char tmpStr[kLineMax + 1];
Common::String line;
@@ -1041,6 +1039,7 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i
error("Bad SPR [%s]", tmpStr);
uint16 len;
+ int i, lcnt = 0;
for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
len = line.size();
lcnt++;
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index c377970c51..11f2a43854 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -24,10 +24,22 @@
#include "engines/advancedDetector.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/translation.h"
#include "base/plugins.h"
#include "graphics/thumbnail.h"
#include "cge/cge.h"
+namespace CGE {
+
+struct CgeGameDescription {
+ ADGameDescription desc;
+ GameType gameType;
+};
+
+#define GAMEOPTION_COLOR_BLIND_DEFAULT_OFF GUIO_GAMEOPTIONS1
+
+} // End of namespace CGE
+
static const PlainGameDescriptor CGEGames[] = {
{ "soltys", "Soltys" },
{ "sfinx", "Sfinx" },
@@ -36,11 +48,6 @@ static const PlainGameDescriptor CGEGames[] = {
namespace CGE {
-struct CgeGameDescription {
- ADGameDescription desc;
- GameType gameType;
-};
-
static const CgeGameDescription gameDescriptions[] = {
{
@@ -63,7 +70,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437676},
AD_LISTEND
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSoltys
},
@@ -75,7 +82,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "75d385a6074c58b69f7730481f256051", 1796710},
AD_LISTEND
},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO0()
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSoltys
},
@@ -87,7 +94,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "c5d9b15863cab61dc125551576dece04", 1075272},
AD_LISTEND
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO0()
+ Common::PL_POL, Common::kPlatformDOS, ADGF_DEMO , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSoltys
},
@@ -99,7 +106,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "4ffeff4abc99ac5999b55ccfc56ab1df", 8430868},
AD_LISTEND
},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0()
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSoltys
},
@@ -111,7 +118,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "0e43331c846094d77f5dd201827e0a3b", 8439339},
AD_LISTEND
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSoltys
},
@@ -123,7 +130,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "ff10d54acc2c95696c57e05819b6906f", 8450151},
AD_LISTEND
},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO0()
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_NO_FLAGS , GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSoltys
},
@@ -136,7 +143,7 @@ static const CgeGameDescription gameDescriptions[] = {
{"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844},
AD_LISTEND
},
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
kGameTypeSfinx
},
@@ -148,12 +155,25 @@ static const ADFileBasedFallback fileBasedFallback[] = {
{ &gameDescriptions[0].desc, { "vol.cat", "vol.dat", 0 } },
{ 0, { 0 } }
};
-
} // End of namespace CGE
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_COLOR_BLIND_DEFAULT_OFF,
+ {
+ _s("Color Blind Mode"),
+ _s("Enable Color Blind Mode by default"),
+ "enable_color_blind",
+ false
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
class CGEMetaEngine : public AdvancedMetaEngine {
public:
- CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames) {
+ CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames, optionsList) {
_singleid = "soltys";
}
@@ -169,8 +189,6 @@ public:
return "Soltys (c) 1994-1996 L.K. Avalon";
}
-
-
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual int getMaximumSaveSlot() const;
@@ -208,10 +226,9 @@ SaveStateList CGEMetaEngine::listSaves(const char *target) const {
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
- int slotNum = 0;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
// Obtain the last 3 digits of the filename, since they correspond to the save slot
- slotNum = atoi(filename->c_str() + filename->size() - 3);
+ int slotNum = atoi(filename->c_str() + filename->size() - 3);
if (slotNum >= 0 && slotNum <= 99) {
diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp
index 4954e638ab..b469c7197d 100644
--- a/engines/cge/vga13h.cpp
+++ b/engines/cge/vga13h.cpp
@@ -26,6 +26,7 @@
*/
#include "common/array.h"
+#include "common/config-manager.h"
#include "common/rect.h"
#include "graphics/palette.h"
#include "cge/general.h"
@@ -210,10 +211,10 @@ Sprite *Sprite::expand() {
error("Bad SPR [%s]", fname);
Common::String line;
char tmpStr[kLineMax + 1];
- int len = 0, lcnt = 0;
+ int lcnt = 0;
for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
- len = line.size();
+ int len = line.size();
Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
lcnt++;
if (len == 0 || *tmpStr == '.')
@@ -637,6 +638,10 @@ Vga::Vga(CGEEngine *vm) : _frmCnt(0), _msg(NULL), _name(NULL), _setPal(false), _
_page[idx]->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
}
+ if (ConfMan.getBool("enable_color_blind"))
+ _mono = 1;
+
+
_oldColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
_newColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
getColors(_oldColors);
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 636c0cf8d9..18a569b9c4 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -246,17 +246,16 @@ void FWRenderer::incrustSprite(const BGIncrust &incrust) {
* Draw command box on screen
*/
void FWRenderer::drawCommand() {
- unsigned int i;
- int x = 10, y = _cmdY;
-
if (disableSystemMenu == 0) {
+ int x = 10, y = _cmdY;
+
drawPlainBox(x, y, 301, 11, 0);
drawBorder(x - 1, y - 1, 302, 12, 2);
x += 2;
y += 2;
- for (i = 0; i < _cmd.size(); i++) {
+ for (unsigned int i = 0; i < _cmd.size(); i++) {
x = drawChar(_cmd[i], x, y);
}
}
@@ -458,12 +457,12 @@ void FWRenderer::drawDoubleBorder(int x, int y, int width, int height, byte colo
* @param y Character coordinate
*/
int FWRenderer::drawChar(char character, int x, int y) {
- int width, idx;
+ int width;
if (character == ' ') {
x += 5;
} else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
- idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
+ int idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
drawSpriteRaw(g_cine->_textHandler.textTable[idx][FONT_DATA], g_cine->_textHandler.textTable[idx][FONT_MASK], FONT_WIDTH, FONT_HEIGHT, _backBuffer, x, y);
x += width + 1;
}
@@ -481,12 +480,12 @@ int FWRenderer::drawChar(char character, int x, int y) {
* @param y Character coordinate
*/
int FWRenderer::undrawChar(char character, int x, int y) {
- int width, idx;
+ int width;
if (character == ' ') {
x += 5;
} else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
- idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
+ int idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
const byte *sprite = g_cine->_textHandler.textTable[idx][FONT_DATA];
for (uint i = 0; i < FONT_HEIGHT; ++i) {
byte *dst = _backBuffer + (y + i) * 320 + x;
@@ -997,11 +996,10 @@ void SelectionMenu::drawMenu(FWRenderer &r, bool top) {
}
int lineY = y + 4;
- int charX;
const int elemCount = getElementCount();
for (int i = 0; i < elemCount; ++i, lineY += 9) {
- charX = x + 4;
+ int charX = x + 4;
if (i == _selection) {
int color;
@@ -1228,12 +1226,12 @@ void OSRenderer::incrustSprite(const BGIncrust &incrust) {
* @param y Character coordinate
*/
int OSRenderer::drawChar(char character, int x, int y) {
- int width, idx;
+ int width;
if (character == ' ') {
x += 5;
} else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
- idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
+ int idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
drawSpriteRaw2(g_cine->_textHandler.textTable[idx][FONT_DATA], 0, FONT_WIDTH, FONT_HEIGHT, _backBuffer, x, y);
x += width + 1;
}
@@ -1834,7 +1832,7 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
}
}
}
- it++;
+ ++it;
}
// now, draw with the mask we created
@@ -1887,7 +1885,6 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he
byte *page, int16 x, int16 y) {
int16 i, j, tmpWidth, tmpHeight;
Common::List<BGIncrust>::iterator it;
- byte *mask;
const byte *backup = maskPtr;
// background pass
@@ -1915,7 +1912,7 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he
for (it = g_cine->_bgIncrustList.begin(); it != g_cine->_bgIncrustList.end(); ++it) {
tmpWidth = g_cine->_animDataTable[it->frame]._realWidth;
tmpHeight = g_cine->_animDataTable[it->frame]._height;
- mask = (byte *)malloc(tmpWidth * tmpHeight);
+ byte *mask = (byte *)malloc(tmpWidth * tmpHeight);
if (it->param == 0) {
generateMask(g_cine->_animDataTable[it->frame].data(), mask, tmpWidth * tmpHeight, it->part);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index c822f1cabd..789e764df3 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -254,7 +254,7 @@ void purgeSeqList() {
it = g_cine->_seqList.erase(it);
} else {
// Let the element be and jump to the next element
- it++;
+ ++it;
}
}
}
diff --git a/engines/fullpipe/constants.h b/engines/fullpipe/constants.h
index 408f765fce..bae0a2d799 100644
--- a/engines/fullpipe/constants.h
+++ b/engines/fullpipe/constants.h
@@ -39,12 +39,17 @@ namespace Fullpipe {
#define MSG_MANSHADOWSOFF 5196
#define MSG_MANSHADOWSON 5197
#define MV_FLY_FLY 4917
+#define MV_LFT_CLOSE 1053
+#define MV_LFT_OPEN 1048
#define MV_MAN_GOLADDER 451
#define MV_MAN_GOLADDER2 2844
+#define MV_MAN_LIFTDOWN 1052
+#define MV_MAN_LIFTUP 1051
#define MV_MAN_LOOKUP 4773
#define rMV_MAN_LOOKUP 4775
#define MV_MAN_TOLADDER 448
#define MV_MAN_TOLADDER2 2841
+#define MV_MAN_STARTD 478
#define MV_MAN_STARTLADDER 452
#define MV_MAN_STARTLADDER2 2842
#define MV_MAN_STOPLADDER 454
@@ -83,6 +88,7 @@ namespace Fullpipe {
#define PIC_CSR_ITN_RED 5329
#define PIC_CSR_LIFT 5176
#define PIC_CSR_MAP 5339
+#define PIC_HLP_BGR 3562
#define PIC_IN1_GAMETITLE 5169
#define PIC_IN1_PIPETITLE 5167
#define PIC_INV_MENU 991
@@ -210,9 +216,11 @@ namespace Fullpipe {
#define SC_INTRO2 3907
#define SC_INV 858
#define SC_LDR 635
+#define SC_MAINMENU 4620
#define SC_MAP 5222
#define SC_TITLES 5166
#define SND_CMN_031 3516
+#define SND_CMN_032 3517
#define SND_CMN_060 4921
#define SND_CMN_061 4922
#define SND_CMN_070 5199
@@ -249,6 +257,8 @@ namespace Fullpipe {
#define ST_LBN_7P 2772
#define ST_LBN_8P 2775
#define ST_LBN_9P 2778
+#define ST_LFT_CLOSED 1049
+#define ST_LFT_OPEN_NEW 1071
#define ST_MAN_EMPTY 476
#define ST_MAN_GOU 459
#define ST_MAN_RIGHT 325
@@ -575,6 +585,33 @@ namespace Fullpipe {
#define ST_MAN8_STAND 774
#define ST_VMT_MIN 766
+// Scene 9
+#define ANI_BALL9 933
+#define ANI_GLOTATEL 924
+#define ANI_GRIT_9 2719
+#define ANI_PLEVATEL 919
+#define ANI_VISUNCHIK 904
+#define MSG_SC9_EATBALL 941
+#define MSG_SC9_FLOWN 943
+#define MSG_SC9_FROMLADDER 4207
+#define MSG_SC9_PLVCLICK 965
+#define MSG_SC9_SETSCROLL 964
+#define MSG_SC9_SHOWBALL 936
+#define MSG_SC9_STARTTIOTIA 4942
+#define MSG_SC9_TOLADDER 4206
+#define MV_GLT_FLYAWAY 931
+#define MV_MAN9_SHOOT 922
+#define MV_VSN_CYCLE2 2987
+#define PIC_SC9_LADDER_R 2700
+#define QU_TTA9_GOL 4937
+#define SND_9_006 3650
+#define SND_9_018 4200
+#define ST_GLT_SIT 926
+#define ST_GRT9_GRIT 2722
+#define ST_GRT9_NORM 2721
+#define ST_PLV_SIT 921
+#define ST_VSN_NORMAL 906
+
// Scene 10
#define ANI_GUM 978
#define ANI_NADUVATEL 944
@@ -1073,6 +1110,52 @@ namespace Fullpipe {
#define ST_VNT26_RIGHT2 3348
#define ST_VNT26_UP2 1948
+// Scene 27
+#define ANI_BITA 2026
+#define ANI_BITAHANDLER 3349
+#define ANI_MAID 2015
+#define ANI_VODILLA 1994
+#define MSG_SC27_CLICKBET 2048
+#define MSG_SC27_HANDLERTOBACK 3372
+#define MSG_SC27_HANDLERTOFRONT 3371
+#define MSG_SC27_SHOWNEXTBET 3369
+#define MSG_SC27_STARTBET 2047
+#define MSG_SC27_STARTWIPE 2057
+#define MSG_SC27_TAKEVENT 4584
+#define MV_BTA_FALL 2049
+#define MV_BTH_1_0 3366
+#define MV_BTH_2_1 3364
+#define MV_BTH_3_2 3362
+#define MV_BTH_4_3 3360
+#define MV_BTH_5_4 3358
+#define MV_MAN27_FLOW 1990
+#define MV_MAN27_THROWBET 1989
+#define PIC_SC27_HITZONE2 4756
+#define QU_DRV_GIVEVENT 2040
+#define QU_DRV_PUSHBUTTON 2056
+#define QU_DRV_PUSHBUTTON_NOVENT 4578
+#define QU_MID_CLEANVENT 4583
+#define QU_MID_SWITCHBACK 2044
+#define QU_SC27_RESTARTBETS 3370
+#define QU_SC27_SHOWBET 3368
+#define SND_27_026 4127
+#define SND_27_027 4128
+#define SND_27_044 4687
+#define ST_BTA_FALL 2054
+#define ST_BTA_HILITE 2052
+#define ST_BTA_NORM 2028
+#define ST_BTH_1 3365
+#define ST_BTH_2 3363
+#define ST_BTH_3 3361
+#define ST_BTH_4 3359
+#define ST_BTH_5 3357
+#define ST_DRV_SITNOVENT 1999
+#define ST_DRV_VENT 1996
+#define ST_MID_BROOM 2022
+#define ST_MID_SPADE 3489
+#define ST_MID_SWAB 2017
+#define ST_MID_SWAB2 2019
+
// Scene 28
#define ANI_LIFT 982
#define ANI_LIFT_28 4238
diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h
index 1e583279f5..3a43f69fb1 100644
--- a/engines/fullpipe/fullpipe.h
+++ b/engines/fullpipe/fullpipe.h
@@ -288,10 +288,11 @@ public:
void lift_clickButton();
void lift_walkAndGo();
void lift_goAnimation();
- void lift_sub1(StaticANIObject *ani);
+ void lift_animateButton(StaticANIObject *button);
void lift_startExitQueue();
- void lift_sub05(ExCommand *ex);
+ void lift_hoverButton(ExCommand *ex);
bool lift_checkButton(const char *varname);
+ void lift_openLift();
GameVar *_musicGameVar;
Audio::SoundHandle _sceneTrackHandle;
diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp
index 2d68600dbb..d72419b645 100644
--- a/engines/fullpipe/gfx.cpp
+++ b/engines/fullpipe/gfx.cpp
@@ -979,6 +979,9 @@ void Bitmap::putDibCB(int32 *palette) {
byte *srcPtr = &_pixels[pitch * (endy - _y)];
+ if (endy - _y < _height)
+ srcPtr = &_pixels[pitch * (_height - 1)];
+
int starty = _y;
if (starty < 0) {
starty = 0;
@@ -992,7 +995,7 @@ void Bitmap::putDibCB(int32 *palette) {
}
if (_flags & 0x1000000) {
- for (int y = starty; y < endy; srcPtr -= pitch, y++) {
+ for (int y = starty; y <= endy; srcPtr -= pitch, y++) {
curDestPtr = (uint16 *)g_fp->_backgroundSurface.getBasePtr(startx, y);
copierKeyColor(curDestPtr, srcPtr, endx - startx + 1, _flags & 0xff, (int32 *)palette, cb05_format);
}
diff --git a/engines/fullpipe/init.cpp b/engines/fullpipe/init.cpp
index 8de37b5c9e..fd90db9e0f 100644
--- a/engines/fullpipe/init.cpp
+++ b/engines/fullpipe/init.cpp
@@ -96,7 +96,7 @@ void FullpipeEngine::initObjectStates() {
setObjectState(sO_Pool, getObjectEnumState(sO_Pool, sO_Overfull));
setObjectState(sO_Board_25, getObjectEnumState(sO_Board_25, sO_NearDudesStairs));
setObjectState(sO_Driver, getObjectEnumState(sO_Driver, sO_WithSteering));
- setObjectState(sO_Janitress, getObjectEnumState(sO_Janitress, sO_WithMop));
+ setObjectState(sO_Maid, getObjectEnumState(sO_Maid, sO_WithSwab));
setObjectState(sO_LeftPipe_29, getObjectEnumState(sO_LeftPipe_29, sO_IsClosed));
setObjectState(sO_LeftPipe_30, getObjectEnumState(sO_LeftPipe_30, sO_IsClosed));
setObjectState(sO_Leg, getObjectEnumState(sO_Leg, sO_ShowingHeel));
diff --git a/engines/fullpipe/inventory.cpp b/engines/fullpipe/inventory.cpp
index f5af0611cb..cf12a8279c 100644
--- a/engines/fullpipe/inventory.cpp
+++ b/engines/fullpipe/inventory.cpp
@@ -31,7 +31,7 @@
namespace Fullpipe {
Inventory::~Inventory() {
- warning("STUB: Inventory::~Inventory()");
+ _itemsPool.clear();
}
bool Inventory::load(MfcArchive &file) {
@@ -90,7 +90,7 @@ Inventory2::Inventory2() {
}
Inventory2::~Inventory2() {
- warning("STUB: Inventory2::~Inventory2()");
+ removeMessageHandler(125, -1);
}
bool Inventory2::loadPartial(MfcArchive &file) { // Inventory2_SerializePartially
@@ -123,7 +123,25 @@ void Inventory2::removeItem(int itemId, int count) {
}
void Inventory2::removeItem2(Scene *sceneObj, int itemId, int x, int y, int priority) {
- warning("STUB: void removeItem2(sc, %d, %d, %d, %d)", itemId, x, y, priority);
+ int idx = getInventoryItemIndexById(itemId);
+
+ if (idx >= 0) {
+ if (_inventoryItems[idx]->itemId >> 16) {
+ removeItem(itemId, 1);
+
+ Scene *sc = g_fp->accessScene(_sceneId);
+
+ if (sc) {
+ StaticANIObject *ani = new StaticANIObject(sc->getStaticANIObject1ById(itemId, -1));
+
+ sceneObj->addStaticANIObject(ani, 1);
+
+ ani->_statics = (Statics *)ani->_staticsList[0];
+ ani->setOXY(x, y);
+ ani->_priority = priority;
+ }
+ }
+ }
}
int Inventory2::getCountItemsWithId(int itemId) {
diff --git a/engines/fullpipe/lift.cpp b/engines/fullpipe/lift.cpp
index aa0c19e475..37c4a300a4 100644
--- a/engines/fullpipe/lift.cpp
+++ b/engines/fullpipe/lift.cpp
@@ -29,6 +29,8 @@
#include "fullpipe/scene.h"
#include "fullpipe/statics.h"
#include "fullpipe/messages.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/motion.h"
namespace Fullpipe {
@@ -217,16 +219,172 @@ void FullpipeEngine::lift_init(Scene *sc, int enterSeq, int exitSeq) {
}
}
-void FullpipeEngine::lift_exitSeq(ExCommand *ex) {
- warning("STUB: FullpipeEngine::lift_exitSeq()");
+void FullpipeEngine::lift_exitSeq(ExCommand *cmd) {
+ if (cmd) {
+ MessageQueue *mq = _globalMessageQueueList->getMessageQueueById(cmd->_parId);
+
+ if (mq)
+ mq->activateExCommandsByKind(34);
+ }
+
+ _lift->changeStatics2(ST_LFT_CLOSED);
+
+ MessageQueue *mq = new MessageQueue(_globalMessageQueueList->compact());
+
+ ExCommand *ex = new ExCommand(_aniMan->_id, 34, 256, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = 256;
+ ex->_messageNum = 256;
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ if (!cmd) {
+ ex = new ExCommand(_aniMan->_id, 2, 40, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _aniMan->_okeyCode;
+ ex->_excFlags |= 2;
+ mq->addExCommandToEnd(ex);
+ }
+
+ ex = new ExCommand(_lift->_id, 1, MV_LFT_OPEN, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _lift->_okeyCode;
+ ex->_excFlags |= 2;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(_aniMan->_id, 1, MV_MAN_STARTD, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _aniMan->_okeyCode;
+ ex->_excFlags |= 2;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(_aniMan->_id, 5, -1, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _aniMan->_okeyCode;
+ ex->_field_14 = 10;
+ ex->_x = -1;
+ ex->_y = -1;
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(_aniMan->_id, 34, 256, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ ex->_field_14 = 256;
+ ex->_messageNum = 0;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(0, 17, MSG_LIFT_STARTEXITQUEUE, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(_lift->_id, 1, MV_LFT_CLOSE, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _lift->_okeyCode;
+ ex->_excFlags |= 2;
+
+ mq->addExCommandToEnd(ex);
+
+ mq->chain(0);
}
void FullpipeEngine::lift_closedoorSeq() {
- warning("STUB: FullpipeEngine::lift_closedoorSeq()");
+ if (_lift->_movement) {
+ if (_lift->_movement->_id == MV_LFT_CLOSE) {
+ _lift->queueMessageQueue(0);
+ } else if (_lift->_movement->_id == MV_LFT_OPEN) {
+ int ph = _lift->_movement->_currDynamicPhaseIndex;
+
+ _lift->changeStatics2(ST_LFT_OPEN_NEW);
+ _lift->startAnim(MV_LFT_CLOSE, 0, -1);
+
+ if (_lift->_movement->_currMovement)
+ _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_currMovement->_dynamicPhases.size() - ph);
+ else
+ _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_dynamicPhases.size() - ph);
+ } else {
+ _lift->changeStatics2(ST_LFT_OPEN_NEW);
+
+ _lift->startAnim(MV_LFT_CLOSE, 0, -1);
+ }
+ } else {
+ if (_lift->_statics->_staticsId == ST_LFT_CLOSED ) {
+ _lift->changeStatics2(ST_LFT_CLOSED);
+ } else {
+ _lift->startAnim(MV_LFT_CLOSE, 0, -1);
+ }
+ }
+
+ MessageQueue *mq = new MessageQueue(_globalMessageQueueList->compact());
+ ExCommand *ex = new ExCommand(0, 17, MSG_LIFT_GO, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ if (!mq->chain(_lift))
+ delete mq;
}
void FullpipeEngine::lift_walkAndGo() {
- warning("STUB: FullpipeEngine::lift_walkAndGo()");
+ MessageQueue *mq;
+ ExCommand *ex;
+
+ if (abs(_liftX - _aniMan->_ox) > 1 || abs(_liftY - _aniMan->_oy) > 1 || _aniMan->_movement || _aniMan->_statics->_staticsId != ST_MAN_UP) {
+ mq = getCurrSceneSc2MotionController()->method34(_aniMan, _liftX, _liftY, 1, ST_MAN_UP);
+
+ if (mq) {
+ ex = new ExCommand(0, 17, MSG_LIFT_CLICKBUTTON, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+
+ mq->addExCommandToEnd(ex);
+ }
+ } else {
+ lift_openLift();
+
+ mq = new MessageQueue(_liftEnterMQ, 0, 0);
+
+ mq->setFlags(mq->getFlags() | 1);
+
+ ex = new ExCommand(_aniMan->_id, 2, 15, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _aniMan->_okeyCode;
+ ex->_excFlags |= 2;
+ mq->addExCommand(ex);
+
+ ex = new ExCommand(_aniMan->_id, 5, -1, 0, 0, 0, 1, 0, 0, 0);
+ ex->_keyCode = _aniMan->_okeyCode;
+ ex->_field_14 = _lift->_priority + 1;
+ ex->_x = -1;
+ ex->_y = -1;
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(0, 17, MSG_LIFT_CLOSEDOOR, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ mq->chain(0);
+
+ _aniMan->_flags |= 1;
+ }
+}
+
+void FullpipeEngine::lift_openLift() {
+ if (_lift->_movement) {
+ if (_lift->_movement->_id == MV_LFT_OPEN) {
+ _lift->queueMessageQueue(0);
+ } else if (_lift->_movement->_id == MV_LFT_CLOSE) {
+ int idx = _lift->_movement->_currDynamicPhaseIndex;
+
+ _lift->changeStatics2(ST_LFT_CLOSED);
+ _lift->startAnim(MV_LFT_OPEN, 0, -1);
+
+ if (_lift->_movement->_currMovement)
+ _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_currMovement->_dynamicPhases.size() - idx);
+ else
+ _lift->_movement->setDynamicPhaseIndex(_lift->_movement->_dynamicPhases.size() - idx);
+ } else {
+ _lift->changeStatics2(ST_LFT_CLOSED);
+ _lift->startAnim(MV_LFT_OPEN, 0, -1);
+ }
+ } else if (_lift->_statics->_staticsId == ST_LFT_OPEN_NEW) {
+ _lift->changeStatics2(ST_LFT_OPEN_NEW);
+ } else {
+ _lift->startAnim(MV_LFT_OPEN, 0, -1);
+ }
}
void FullpipeEngine::lift_clickButton() {
@@ -234,12 +392,89 @@ void FullpipeEngine::lift_clickButton() {
lift_walkAndGo();
}
-void FullpipeEngine::lift_goAnimation() {
- warning("STUB: FullpipeEngine::lift_goAnimation()");
+void FullpipeEngine::lift_goAnimation() { if (_lastLiftButton) {
+ int parentId = _currentScene->_sceneId;
+ int buttonId = lift_getButtonIdN(_lastLiftButton->_statics->_staticsId);
+
+ if (!buttonId)
+ return;
+
+ int numItems = _gameLoader->_preloadItems.size();
+
+ for (int i = 0; i < numItems; i++) {
+ PreloadItem *pre = _gameLoader->_preloadItems[i];
+
+ if (pre->preloadId2 == buttonId && pre->preloadId1 == _currentScene->_sceneId) {
+ MessageQueue *mq = new MessageQueue(_globalMessageQueueList->compact());
+
+ ExCommand *ex = new ExCommand(ANI_MAN, 1, (pre->keyCode != LiftDown ? MV_MAN_LIFTDOWN : MV_MAN_LIFTUP), 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_keyCode = -1;
+ ex->_field_24 = 1;
+ ex->_excFlags |= 2;
+
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(parentId, 17, 61, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_keyCode = buttonId;
+ ex->_excFlags |= 3;
+
+ mq->addExCommandToEnd(ex);
+
+ _aniMan->_flags &= 0xFEFF;
+
+ if (!mq->chain(_aniMan))
+ delete mq;
+
+ _aniMan->_flags |= 1;
+ }
+ }
+ }
+
+ lift_exitSeq(0);
+
+ if (_lastLiftButton) {
+ _lastLiftButton->_statics = _lastLiftButton->getStaticsById(lift_getButtonIdN(_lastLiftButton->_statics->_staticsId));
+ _lastLiftButton = 0;
+ }
}
-void FullpipeEngine::lift_sub1(StaticANIObject *ani) {
- warning("STUB: FullpipeEngine::lift_sub1()");
+void FullpipeEngine::lift_animateButton(StaticANIObject *button) {
+ int butId = lift_getButtonIdP(button->_statics->_staticsId);
+
+ if (butId && butId != button->_statics->_staticsId) {
+ if (button == _lastLiftButton) {
+ playSound(SND_CMN_032, 0);
+ } else {
+ if (_lastLiftButton) {
+ int id = lift_getButtonIdN(_lastLiftButton->_statics->_staticsId);
+
+ if (id)
+ _lastLiftButton->_statics = _lastLiftButton->getStaticsById(id);
+
+ _lastLiftButton = 0;
+ }
+
+ if (_aniMan->isIdle() && !(_aniMan->_flags & 0x100)) {
+ _lastLiftButton = button;
+ button->_statics = button->getStaticsById(butId);
+
+ ExCommand *ex = new ExCommand(0, 35, SND_CMN_032, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ ex->_field_14 = 1;
+ ex->postMessage();
+
+ int id = lift_getButtonIdH(_lastLiftButton->_statics->_staticsId);
+
+ if (id) {
+ _lastLiftButton->_statics = _lastLiftButton->getStaticsById(id);
+
+ lift_walkAndGo();
+ }
+ }
+ }
+ }
}
void FullpipeEngine::lift_startExitQueue() {
@@ -248,12 +483,20 @@ void FullpipeEngine::lift_startExitQueue() {
mq->chain(0);
}
-void FullpipeEngine::lift_sub05(ExCommand *ex) {
- warning("STUB: FullpipeEngine::lift_sub05()");
+void FullpipeEngine::lift_hoverButton(ExCommand *cmd) {
+ if (_lastLiftButton) {
+ if (!(cmd->_keyCode & 2) || _liftX != cmd->_x || _liftY != cmd->_y) {
+ _lastLiftButton->_statics = _lastLiftButton->getStaticsById(lift_getButtonIdN(_lastLiftButton->_statics->_staticsId));
+ _lastLiftButton = 0;
+ }
+ }
}
-bool FullpipeEngine::lift_checkButton(const char *varname) {
- warning("STUB: FullpipeEngine::lift_checkButton(%s)", varname);
+bool FullpipeEngine::lift_checkButton(const char *varName) {
+ GameVar *var = g_fp->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
+
+ if (var)
+ return lift_getButtonIdP(var->getSubVarByName(varName)->_value.intValue) > 0;
return false;
}
diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp
index 7dfdd06fc8..55b5daaeaa 100644
--- a/engines/fullpipe/messages.cpp
+++ b/engines/fullpipe/messages.cpp
@@ -610,6 +610,23 @@ void MessageQueue::changeParam28ForObjectId(int objId, int oldParam28, int newPa
}
}
+int MessageQueue::activateExCommandsByKind(int kind) {
+ int res = 0;
+
+ for (uint i = 0; i < getCount(); i++) {
+ ExCommand *ex = getExCommandByIndex(i);
+
+ if (ex->_messageKind == kind) {
+ ex->_messageKind = 0;
+ ex->_excFlags |= 1;
+
+ res++;
+ }
+ }
+
+ return res;
+}
+
MessageQueue *GlobalMessageQueueList::getMessageQueueById(int id) {
for (Common::Array<MessageQueue *>::iterator s = begin(); s != end(); ++s) {
if ((*s)->_id == id)
diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h
index 33bb827888..f8e9d16a73 100644
--- a/engines/fullpipe/messages.h
+++ b/engines/fullpipe/messages.h
@@ -158,6 +158,8 @@ class MessageQueue : public CObject {
int calcDuration(StaticANIObject *obj);
void changeParam28ForObjectId(int objId, int oldParam28, int newParam28);
+
+ int activateExCommandsByKind(int kind);
};
class GlobalMessageQueueList : public Common::Array<MessageQueue *> {
diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp
index f52dc95a7c..2e7b33b050 100644
--- a/engines/fullpipe/modal.cpp
+++ b/engines/fullpipe/modal.cpp
@@ -755,8 +755,75 @@ ModalMainMenu::ModalMainMenu() {
_field_34 = 0;
}
+ModalHelp::ModalHelp() {
+ _mainMenuScene = 0;
+ _bg = 0;
+ _isRunning = false;
+ _rect = g_fp->_sceneRect;
+ _hx = g_fp->_currentScene->_x;
+ _hy = g_fp->_currentScene->_y;
+
+ g_fp->_sceneRect.left = 0;
+ g_fp->_sceneRect.bottom = 600;
+ g_fp->_sceneRect.top = 0;
+ g_fp->_sceneRect.right = 800;
+}
+
+ModalHelp::~ModalHelp() {
+ g_fp->_gameLoader->unloadScene(SC_MAINMENU);
+
+ g_fp->_sceneRect = _rect;
+
+ g_fp->_currentScene->_x = _hx;
+ g_fp->_currentScene->_y = _hy;
+}
+
+bool ModalHelp::handleMessage(ExCommand *cmd) {
+ if (cmd->_messageKind == 17) {
+ int msg = cmd->_messageNum;
+
+ if (msg == 29 || msg == 36 || msg == 107) {
+ _isRunning = 0;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ModalHelp::init(int counterdiff) {
+ g_fp->setCursor(PIC_CSR_DEFAULT);
+
+ return _isRunning;
+}
+
+void ModalHelp::update() {
+ g_fp->_sceneRect.left = 0;
+ g_fp->_sceneRect.top = 0;
+ g_fp->_sceneRect.right = 800;
+ g_fp->_sceneRect.bottom = 600;
+
+ _bg->draw(0, 0, 0, 0);
+}
+
+void ModalHelp::launch() {
+ _mainMenuScene = g_fp->accessScene(SC_MAINMENU);
+
+ if (_mainMenuScene) {
+ _bg = _mainMenuScene->getPictureObjectById(PIC_HLP_BGR, 0)->_picture;
+ _isRunning = 1;
+ }
+}
+
void FullpipeEngine::openHelp() {
- warning("STUB: FullpipeEngine::openHelp()");
+ if (!_modalObject) {
+ ModalHelp *help = new ModalHelp;
+
+ _modalObject = help;
+
+ help->launch();
+ }
}
void FullpipeEngine::openMainMenu() {
diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h
index 438e341c1c..aa9b997cd1 100644
--- a/engines/fullpipe/modal.h
+++ b/engines/fullpipe/modal.h
@@ -26,6 +26,7 @@
namespace Fullpipe {
class PictureObject;
+class Picture;
class BaseModalObject {
public:
@@ -161,6 +162,52 @@ public:
virtual void saveload() {}
};
+class ModalHelp : public BaseModalObject {
+public:
+ Scene *_mainMenuScene;
+ Picture *_bg;
+ bool _isRunning;
+ Common::Rect _rect;
+ int _hx;
+ int _hy;
+
+public:
+ ModalHelp();
+ virtual ~ModalHelp();
+
+ virtual bool pollEvent() { return true; }
+ virtual bool handleMessage(ExCommand *message);
+ virtual bool init(int counterdiff);
+ virtual void update();
+ virtual void saveload() {}
+
+ void launch();
+};
+
+class ModalQuery : public BaseModalObject {
+public:
+ ModalQuery();
+ virtual ~ModalQuery() {}
+
+ virtual bool pollEvent() { return true; }
+ virtual bool handleMessage(ExCommand *message) { return false; }
+ virtual bool init(int counterdiff) { return true; }
+ virtual void update() {}
+ virtual void saveload() {}
+};
+
+class ModalSaveGame : public BaseModalObject {
+public:
+ ModalSaveGame();
+ virtual ~ModalSaveGame() {}
+
+ virtual bool pollEvent() { return true; }
+ virtual bool handleMessage(ExCommand *message) { return false; }
+ virtual bool init(int counterdiff) { return true; }
+ virtual void update() {}
+ virtual void saveload() {}
+};
+
} // End of namespace Fullpipe
diff --git a/engines/fullpipe/module.mk b/engines/fullpipe/module.mk
index f6a94de421..db97fa202b 100644
--- a/engines/fullpipe/module.mk
+++ b/engines/fullpipe/module.mk
@@ -33,6 +33,7 @@ MODULE_OBJS = \
scenes/scene06.o \
scenes/scene07.o \
scenes/scene08.o \
+ scenes/scene09.o \
scenes/scene10.o \
scenes/scene11.o \
scenes/scene12.o \
@@ -49,6 +50,7 @@ MODULE_OBJS = \
scenes/scene24.o \
scenes/scene25.o \
scenes/scene26.o \
+ scenes/scene27.o \
scenes/scene28.o \
scenes/scene30.o \
scenes/scene31.o \
diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp
index f0318581f1..61612a2ca4 100644
--- a/engines/fullpipe/motion.cpp
+++ b/engines/fullpipe/motion.cpp
@@ -1814,6 +1814,204 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) {
warning("STUB: MGM::genMovement()");
return 0;
+
+#if 0
+ if (!mgminfo->ani)
+ return 0;
+
+ mov = mgminfo->ani->_movement;
+
+ if (!mov && !mgminfo->ani->_statics)
+ return 0;
+
+ if (!(mgminfo->flags & 1)) {
+ if (mov)
+ mgminfo->staticsId1 = mov->_staticsObj2->_staticsId;
+ else
+ mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId;
+ }
+
+ if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) {
+ int nx = mgminfo->ani->_ox;
+ int ny = mgminfo->ani->_oy;
+
+ if (mgminfo->ani->_movement) {
+ mgminfo->ani->calcNextStep(&point2);
+ nx += point2.x;
+ ny += point2.y;
+ }
+
+ if (!(mgminfo->flags & 0x10))
+ mgminfo->x2 = nx;
+
+ if (!(mgminfo->flags & 0x20))
+ mgminfo->y2 = ny;
+ }
+
+ mov = mgminfo->ani->getMovementById(mgminfo->movementId);
+
+ if (!mov)
+ return 0;
+
+ itemIdx = getItemIndexById(mgminfo->ani->_id);
+ subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1);
+ st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId);
+ st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId);
+ subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2);
+
+ clearMovements2(itemIdx);
+ recalcOffsets(itemIdx, subIdx, st2idx, 0, 1);
+ clearMovements2(itemIdx);
+ recalcOffsets(itemIdx, st1idx, subOffset, 0, 1);
+
+ v71 = (Message *)(28 * itemIdx);
+ v16 = items[itemIdx].objId;
+ v17 = *(_DWORD *)(v16 + offsetof(MGMItem, staticsListCount));
+ off = *(_DWORD *)(v16 + offsetof(MGMItem, subItems));
+ v18 = (MGMSubItem *)(off + 24 * (subIdx + st2idx * v17));
+ x1 = (int)&v18->movement->go.CObject.vmt;
+ v19 = (MGMSubItem *)(off + 24 * (st1idx + subOffset * v17));
+ v69 = (LONG)&v19->movement->go.CObject.vmt;
+
+ if (subIdx != st2idx && !x1)
+ return 0;
+
+ if (st1idx != subOffset && !v69)
+ return 0;
+
+ int n1x = mgminfo->x1 - mgminfo->x2 - v18->x - v19->x;
+ int n1y = mgminfo->y1 - mgminfo->y2 - v18->y - v19->y;
+
+ mov->calcSomeXY(&point1, 0);
+
+ int n2x = point1.x;
+ int n2y = point1.y;
+ int mult;
+
+ if (mgminfo->flags & 0x40) {
+ mult = mgminfo->field_10;
+ len = -1;
+ n2x *= mult;
+ n2y *= mult;
+ } else {
+ calcLength(&point, mov, n1x, n1y, &mult, &len, 1);
+ n2x = point.x;
+ n2y = point.y;
+ }
+
+ if (!(mgminfo->flags & 2)) {
+ len = -1;
+ n2x = mult * point1.x;
+ n1x = mult * point1.x;
+ mgminfo->x1 = mgminfo->x2 + mult * point1.x + v18->x + v19->x;
+ }
+
+ if (!(mgminfo->flags & 4)) {
+ n2y = mult * point1.y;
+ n1y = mult * point1.y;
+ len = -1;
+ mgminfo->y1 = mgminfo->y2 + mult * point1.y + v18->y + v19->y;
+ }
+
+ int px = 0;
+ int py = 0;
+
+ if (x1) {
+ px = countPhases(itemIdx, subIdx, st2idx, 1);
+ py = countPhases(itemIdx, subIdx, st2idx, 2);
+ }
+
+ if (mult > 1) {
+ px += (mult - 1) * mov->countPhasesWithFlag(-1, 1);
+ py += (mult - 1) * mov->countPhasesWithFlag(-1, 2);
+ }
+
+ if (mult > 0) {
+ px += mov->countPhasesWithFlag(len, 1);
+ py += mov->countPhasesWithFlag(len, 2);
+ }
+
+ if (v69) {
+ px += countPhases(itemIdx, st1idx, subOffset, 1);
+ py += countPhases(itemIdx, st1idx, subOffset, 2);
+ }
+
+ int dx1 = n1x - n2x;
+ int dy1 = n1y - n2y;
+
+ if (px) {
+ x1 = (int)((double)dx1 / (double)px);
+ } else {
+ x1 = 0;
+ }
+
+ if (py) {
+ y1 = (int)((double)dy1 / (double)py);
+ } else {
+ y1 = 0;
+ }
+
+ y2.x = dx1 - px * x1;
+ y2.y = dy1 - py * y1;
+
+ if (n1x - n2x == px * x1)
+ x2.x = 0;
+ else
+ x2.x = (dx1 - px * x1) / abs(dx1 - px * x1);
+
+ if (dy1 == py * y1)
+ x2.y = 0;
+ else
+ x2.y = (dy1 - py * y1) / abs(dy1 - py * y1);
+
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+ ExCommand2 *ex2;
+
+ for (v42 = subIdx; v42 != st2idx; v42 = v43->staticsIndex) {
+ v43 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[v42 + st2idx * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)];
+ ex2 = buildExCommand2(v43->movement, mgminfo->ani->go._id, x1, y1, &x2, &y2, -1);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ for (i = 0; i < mult; ++i) {
+ int plen;
+
+ if (i == mult - 1)
+ plen = len;
+ else
+ plen = -1;
+
+ ex2 = buildExCommand2(mov, mgminfo->ani->_id, x1, y1, &x2, &y2, plen);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ for (j = st1idx; j != subOffset; j = v50->staticsIndex) {
+ v50 = &(*(MGMSubItem **)((char *)&this->items->subItems + (unsigned int)v71))[j + subOffset * *(int *)((char *)&this->items->staticsListCount + (unsigned int)v71)];
+
+ ex2 = buildExCommand2(v50->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1);
+ ex2->_parId = mq->_id;
+ ex2->_keyCode = mgminfo->ani->_okeyCode;
+
+ mq->addExCommandToEnd(ex2);
+ }
+
+ ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = mgminfo->field_1C;
+ ex->_keyCode = mgminfo->ani->_okeyCode;
+ ex->_field_24 = 0;
+ ex->_excFlags |= 3;
+
+ mq->addExCommandToEnd(ex);
+
+ return mq;
+#endif
}
void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) {
@@ -1919,34 +2117,34 @@ int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) {
return 0;
}
-Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *x1, int *y1, int flag) {
+Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) {
Common::Point point;
mov->calcSomeXY(point, 0);
int p1x = point.x;
int p1y = point.y;
- int newx1 = 0;
- int oldy1 = *y1;
+ int newmult = 0;
+ int oldlen = *len;
if (abs(p1y) > abs(p1x)) {
if (mov->calcSomeXY(point, 0)->y)
- newx1 = (int)((double)y / point.y);
+ newmult = (int)((double)y / point.y);
} else if (mov->calcSomeXY(point, 0)->x) {
- newx1 = (int)((double)x / point.y);
+ newmult = (int)((double)x / point.y);
}
- if (newx1 < 0)
- newx1 = 0;
+ if (newmult < 0)
+ newmult = 0;
- *x1 = newx1;
+ *mult = newmult;
int phase = 1;
int sz;
if (flag) {
if (abs(p1y) > abs(p1x)) {
- while (abs(p1y * newx1 + mov->calcSomeXY(point, 0)->y) < abs(y)) {
+ while (abs(p1y * newmult + mov->calcSomeXY(point, 0)->y) < abs(y)) {
sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
if (phase >= sz) {
@@ -1958,7 +2156,7 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y,
phase++;
}
} else {
- while (abs(p1x * newx1 + mov->calcSomeXY(point, 0)->x) < abs(x)) {
+ while (abs(p1x * newmult + mov->calcSomeXY(point, 0)->x) < abs(x)) {
sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size();
if (phase >= sz) {
@@ -1971,19 +2169,19 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y,
}
}
- *y1 = phase - 1;
+ *len = phase - 1;
} else {
- *y1 = -1;
+ *len = -1;
}
int p2x = 0;
int p2y = 0;
- if (!oldy1)
- oldy1 = -1;
+ if (!oldlen)
+ oldlen = -1;
- if (oldy1 > 0) {
- ++*x1;
+ if (oldlen > 0) {
+ ++*mult;
mov->calcSomeXY(point, 0);
p2x = point.x;
@@ -1995,8 +2193,8 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y,
p2y = p1y;
}
- pRes->x = p2x + p1x * newx1;
- pRes->y = p2y + p1y * newx1;
+ pRes->x = p2x + p1x * newmult;
+ pRes->y = p2y + p1y * newmult;
return pRes;
}
diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h
index 6ad46e719a..8ca1cdff57 100644
--- a/engines/fullpipe/motion.h
+++ b/engines/fullpipe/motion.h
@@ -176,7 +176,7 @@ public:
int getStaticsIndex(int idx, Statics *st);
void clearMovements2(int idx);
int recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop);
- Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *x1, int *y1, int flag);
+ Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag);
ExCommand2 *buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len);
};
diff --git a/engines/fullpipe/objectnames.h b/engines/fullpipe/objectnames.h
index eafdb2a8e7..a3718519ca 100644
--- a/engines/fullpipe/objectnames.h
+++ b/engines/fullpipe/objectnames.h
@@ -192,7 +192,7 @@ namespace Fullpipe {
#define sO_WithPlunger "\xd1 \xe2\xe0\xed\xf2\xf3\xe7\xee\xec" // "С вантузом"
#define sO_WithJug "\xd1 \xe3\xee\xf0\xf8\xea\xee\xec" // "С горшком"
#define sO_WithGum "\xd1 \xe6\xe2\xe0\xf7\xea\xee\xe9" // "С жвачкой"
-#define sO_WithShovel "\xd1 \xeb\xee\xef\xe0\xf2\xee\xe9" // "С лопатой"
+#define sO_WithSpade "\xd1 \xeb\xee\xef\xe0\xf2\xee\xe9" // "С лопатой"
#define sO_WithSmall "\xd1 \xec\xe0\xeb\xfb\xec" // "С малым"
#define sO_WithHammer "\xd1 \xec\xee\xeb\xee\xf2\xea\xee\xec" // "С молотком"
#define sO_WithCoin "\xd1 \xec\xee\xed\xe5\xf2\xee\xe9" // "С монетой"
@@ -208,9 +208,9 @@ namespace Fullpipe {
#define sO_IsSitting "\xd1\xe8\xe4\xe8\xf2" // "Сидит"
#define sO_IsLaughing "\xd1\xec\xe5\xe5\xf2\xf1\xff" // "Смеется"
#define sO_WithAll "\xd1\xee \xe2\xf1\xe5\xec\xe8" // "Со всеми"
-#define sO_WithMop "\xd1\xee \xf8\xe2\xe0\xe1\xf0\xee\xe9" // "Со шваброй"
+#define sO_WithSwab "\xd1\xee \xf8\xe2\xe0\xe1\xf0\xee\xe9" // "Со шваброй"
#define sO_WithHose "\xd1\xee \xf8\xeb\xe0\xed\xe3\xee\xec" // "Со шлангом"
-#define sO_WithBrush "\xd1\xee \xf9\xe5\xf2\xea\xee\xe9" // "Со щеткой"
+#define sO_WithBroom "\xd1\xee \xf9\xe5\xf2\xea\xee\xe9" // "Со щеткой"
#define sO_IsSleeping "\xd1\xef\xe8\xf2" // "Спит"
#define sO_OnRight "\xd1\xef\xf0\xe0\xe2\xe0" // "Справа"
#define sO_IsStandingInBoots "\xd1\xf2\xee\xe8\xf2 \xe2 \xe1\xee\xf2\xe8\xed\xea\xe0\xf5" // "Стоит в ботинках"
@@ -229,7 +229,7 @@ namespace Fullpipe {
#define sO_NearPipeWithStool "\xd3 \xf2\xf0\xf3\xe1\xfb \xf1 \xf2\xe0\xe1\xf3\xf0\xe5\xf2\xea\xee\xe9" // "У трубы с табуреткой"
#define sO_NearPipe "\xd3 \xf2\xf0\xf3\xe1\xfb" // "У трубы"
#define sO_Janitors "\xd3\xe1\xee\xf0\xf9\xe8\xea\xe8" // "Уборщики"
-#define sO_Janitress "\xd3\xe1\xee\xf0\xf9\xe8\xf6\xe0" // "Уборщица"
+#define sO_Maid "\xd3\xe1\xee\xf0\xf9\xe8\xf6\xe0" // "Уборщица"
#define sO_IsGone "\xd3\xe5\xf5\xe0\xeb\xe0" // "Уехала"
#define sO_FallenTwice "\xd3\xef\xe0\xeb \xe4\xe2\xe0" // "Упал два"
#define sO_FallenOnce "\xd3\xef\xe0\xeb \xf0\xe0\xe7" // "Упал раз"
diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp
index 71c8b1efb5..96de1448c4 100644
--- a/engines/fullpipe/scenes.cpp
+++ b/engines/fullpipe/scenes.cpp
@@ -31,6 +31,7 @@
#include "fullpipe/behavior.h"
#include "fullpipe/constants.h"
+#include "fullpipe/objectnames.h"
#include "fullpipe/scenes.h"
#include "fullpipe/interaction.h"
@@ -155,6 +156,25 @@ Vars::Vars() {
scene08_stairsVisible = true;
scene08_manOffsetY = 0;
+ scene09_flyingBall = 0;
+ scene09_var05 = 0;
+ scene09_glotatel = 0;
+ scene09_spitter = 0;
+ scene09_grit = 0;
+ scene09_var02 = 0;
+ scene09_var08 = 1;
+ scene09_var09 = 0;
+ scene09_var10 = -1;
+ scene09_var11 = -1;
+ scene09_var12 = -1000;
+ scene09_numMovingHangers = 0;
+ scene09_var13 = 0;
+ scene09_var15 = 0;
+ scene09_var17 = 0;
+ scene09_var19 = 0;
+ scene09_var18.x = 0;
+ scene09_var18.y = -15;
+
scene10_gum = 0;
scene10_packet = 0;
scene10_packet2 = 0;
@@ -300,6 +320,22 @@ Vars::Vars() {
scene26_sock = 0;
scene26_activeVent = 0;
+ scene27_hitZone = 0;
+ scene27_driver = 0;
+ scene27_maid = 0;
+ scene27_batHandler = 0;
+ scene27_driverHasVent = true;
+ scene27_bat = 0;
+ scene27_dudeIsAiming = false;
+ scene27_maxPhaseReached = false;
+ scene27_wipeIsNeeded = false;
+ scene27_driverPushedButton = false;
+ scene27_numLostBats = 0;
+ scene27_knockCount = 0;
+ scene27_aimStartX = 0;
+ scene27_aimStartY = 0;
+ scene27_launchPhase = 0;
+
scene28_fliesArePresent = true;
scene28_beardedDirection = true;
scene28_darkeningObject = 0;
@@ -618,7 +654,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
_updateCursorCallback = scene08_updateCursor;
break;
-#if 0
case SC_9:
sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_9");
scene->preloadMovements(sceneVar);
@@ -629,7 +664,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
insertMessageHandler(sceneHandler09, 2, 2);
_updateCursorCallback = scene09_updateCursor;
break;
-#endif
case SC_10:
sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_10");
@@ -847,7 +881,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
_updateCursorCallback = scene26_updateCursor;
break;
-#if 0
case SC_27:
sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_27");
scene->preloadMovements(sceneVar);
@@ -858,7 +891,6 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
addMessageHandler(sceneHandler27, 2);
_updateCursorCallback = scene27_updateCursor;
break;
-#endif
case SC_28:
sceneVar = _gameLoader->_gameVar->getSubVarByName("SC_28");
@@ -1211,7 +1243,7 @@ void FullpipeEngine::updateMap(PreloadItem *pre) {
break;
case SC_23:
- if (getObjectState("Верхний люк_23") == getObjectEnumState("Верхний люк_23", "Открыт")) {
+ if (getObjectState(sO_UpperHatch_23) == getObjectEnumState(sO_UpperHatch_23, sO_Opened)) {
updateMapPiece(PIC_MAP_S23_1, 0);
updateMapPiece(PIC_MAP_S23_2, 1);
updateMapPiece(PIC_MAP_P07, 1);
@@ -1284,7 +1316,7 @@ void FullpipeEngine::updateMap(PreloadItem *pre) {
case SC_31:
updateMapPiece(PIC_MAP_S31_2, 1);
- if (getObjectState("Кактус") == getObjectEnumState("Кактус", "Вырос"))
+ if (getObjectState(sO_Cactus) == getObjectEnumState(sO_Cactus, sO_HasGrown))
updateMapPiece(PIC_MAP_S31_1, 1);
if (pre->keyCode == TrubaRight)
@@ -1295,7 +1327,7 @@ void FullpipeEngine::updateMap(PreloadItem *pre) {
case SC_32:
updateMapPiece(PIC_MAP_S32_2, 1);
- if (getObjectState("Кактус") == getObjectEnumState("Кактус", "Вырос"))
+ if (getObjectState(sO_Cactus) == getObjectEnumState(sO_Cactus, sO_HasGrown))
updateMapPiece(PIC_MAP_S32_1, 1);
break;
@@ -1356,5 +1388,28 @@ void FullpipeEngine::updateMap(PreloadItem *pre) {
}
}
+void BallChain::init(Ball **ball) {
+ *ball = pTail;
+ pTail = (Ball *)ball;
+ numBalls--;
+
+ if (!numBalls) {
+ for (Ball *i = pHead; i; i = i->p0 )
+ ;
+ numBalls = 0;
+ pTail = 0;
+ field_8 = 0;
+ pHead = 0;
+ free(cPlex);
+ cPlex = 0;
+ }
+}
+
+Ball *BallChain::sub04(Ball *ballP, Ball *ballN) {
+ warning("STUB: BallChain::sub04");
+
+ return pTail;
+}
+
} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes.h b/engines/fullpipe/scenes.h
index 5f77f74706..6b4c7e3632 100644
--- a/engines/fullpipe/scenes.h
+++ b/engines/fullpipe/scenes.h
@@ -25,7 +25,9 @@
namespace Fullpipe {
+struct Bat;
struct BehaviorEntryInfo;
+struct Hanger;
class MGM;
class MctlLadder;
struct Ring;
@@ -69,6 +71,10 @@ void scene08_setupMusic();
int sceneHandler08(ExCommand *cmd);
int scene08_updateCursor();
+int scene09_updateCursor();
+void scene09_initScene(Scene *sc);
+int sceneHandler09(ExCommand *cmd);
+
void scene10_initScene(Scene *sc);
int sceneHandler10(ExCommand *cmd);
int scene10_updateCursor();
@@ -136,8 +142,12 @@ void scene26_setupDrop(Scene *sc);
int sceneHandler26(ExCommand *cmd);
int scene26_updateCursor();
+void scene27_initScene(Scene *sc);
+int sceneHandler27(ExCommand *ex);
+int scene27_updateCursor();
+
void scene28_initScene(Scene *sc);
- int sceneHandler28(ExCommand *ex);
+int sceneHandler28(ExCommand *ex);
int scene28_updateCursor();
int scene30_updateCursor();
@@ -183,6 +193,30 @@ int sceneHandlerFinal(ExCommand *cmd);
void sceneDbgMenu_initScene(Scene *sc);
int sceneHandlerDbgMenu(ExCommand *cmd);
+struct Ball {
+ Ball *p0;
+ Ball *p1;
+ StaticANIObject *ani;
+
+ Ball() : p0(0), p1(0), ani(0) {}
+};
+
+struct BallChain {
+ Ball *pHead;
+ Ball *field_8;
+ int numBalls;
+ Ball *pTail;
+ byte *cPlex;
+ int cPlexLen;
+
+ BallChain() : pHead(0), field_8(0), pTail(0), numBalls(0), cPlex(0), cPlexLen(0) {}
+ ~BallChain() { free(cPlex); }
+
+ void init(Ball **ball);
+ Ball *sub04(Ball *ballP, Ball *ballN);
+ void reset() { pHead = 0; pTail = 0; field_8 = 0; numBalls = 0; free(cPlex); cPlex = 0; cPlexLen = 0; }
+};
+
class Vars {
public:
Vars();
@@ -314,6 +348,27 @@ public:
bool scene08_stairsVisible;
int scene08_manOffsetY;
+ int scene09_var02;
+ StaticANIObject *scene09_flyingBall;
+ int scene09_var05;
+ StaticANIObject *scene09_glotatel;
+ StaticANIObject *scene09_spitter;
+ StaticANIObject *scene09_grit;
+ int scene09_var08;
+ int scene09_var09;
+ int scene09_var10;
+ int scene09_var11;
+ int scene09_var12;
+ BallChain scene09_balls;
+ Common::Array<Hanger *> scene09_hangers;
+ BallChain scene09_var07;
+ int scene09_numMovingHangers;
+ int scene09_var13;
+ int scene09_var15;
+ int scene09_var17;
+ int scene09_var19;
+ Common::Point scene09_var18;
+
StaticANIObject *scene10_gum;
StaticANIObject *scene10_packet;
StaticANIObject *scene10_packet2;
@@ -461,6 +516,25 @@ public:
StaticANIObject *scene26_sock;
StaticANIObject *scene26_activeVent;
+ PictureObject *scene27_hitZone;
+ StaticANIObject *scene27_driver;
+ StaticANIObject *scene27_maid;
+ StaticANIObject *scene27_batHandler;
+ bool scene27_driverHasVent;
+ StaticANIObject *scene27_bat;
+ bool scene27_dudeIsAiming;
+ bool scene27_maxPhaseReached;
+ bool scene27_wipeIsNeeded;
+ bool scene27_driverPushedButton;
+ int scene27_numLostBats;
+ int scene27_knockCount;
+ int scene27_aimStartX;
+ int scene27_aimStartY;
+ int scene27_launchPhase;
+ BallChain scene27_balls;
+ Common::Array<Bat *> scene27_bats;
+ Common::Array<Bat *> scene27_var07;
+
bool scene28_fliesArePresent;
bool scene28_beardedDirection;
PictureObject *scene28_darkeningObject;
diff --git a/engines/fullpipe/scenes/scene03.cpp b/engines/fullpipe/scenes/scene03.cpp
index 9ba84a540a..5d22931fb7 100644
--- a/engines/fullpipe/scenes/scene03.cpp
+++ b/engines/fullpipe/scenes/scene03.cpp
@@ -239,14 +239,14 @@ int sceneHandler03(ExCommand *ex) {
break;
case 64:
- g_fp->lift_sub05(ex);
+ g_fp->lift_hoverButton(ex);
break;
case 29:
{
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
ex->_messageKind = 0;
return 0;
diff --git a/engines/fullpipe/scenes/scene06.cpp b/engines/fullpipe/scenes/scene06.cpp
index 7d637d8306..83b98c2722 100644
--- a/engines/fullpipe/scenes/scene06.cpp
+++ b/engines/fullpipe/scenes/scene06.cpp
@@ -622,7 +622,7 @@ int sceneHandler06(ExCommand *ex) {
break;
case 64:
- g_fp->lift_sub05(ex);
+ g_fp->lift_hoverButton(ex);
break;
case MSG_SC6_TAKEBALL:
@@ -647,7 +647,7 @@ int sceneHandler06(ExCommand *ex) {
if (st) {
if (!g_vars->scene06_arcadeEnabled && st->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(st);
+ g_fp->lift_animateButton(st);
ex->_messageKind = 0;
return 0;
}
diff --git a/engines/fullpipe/scenes/scene09.cpp b/engines/fullpipe/scenes/scene09.cpp
new file mode 100644
index 0000000000..6752864962
--- /dev/null
+++ b/engines/fullpipe/scenes/scene09.cpp
@@ -0,0 +1,484 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/statics.h"
+
+#include "fullpipe/interaction.h"
+#include "fullpipe/behavior.h"
+
+
+namespace Fullpipe {
+
+struct Hanger {
+ StaticANIObject *ani;
+ int field_4;
+ int field_8;
+ int phase;
+};
+
+void scene09_setupGrit(Scene *sc) {
+ if (g_vars->scene09_grit->_statics->_staticsId == ST_GRT9_GRIT) {
+ if (!getGameLoaderInventory()->getCountItemsWithId(ANI_INV_COIN)) {
+ if (g_fp->getObjectState(sO_CoinSlot_1) == g_fp->getObjectEnumState(sO_CoinSlot_1, sO_Empty)
+ && (g_vars->swallowedEgg1->_value.intValue == ANI_INV_EGGBOOT || g_vars->swallowedEgg2->_value.intValue == ANI_INV_EGGBOOT || g_vars->swallowedEgg3->_value.intValue == ANI_INV_EGGBOOT)) {
+ Scene *oldsc = g_fp->_currentScene;
+ g_fp->_currentScene = sc;
+ g_vars->scene09_grit->changeStatics2(ST_GRT9_NORM);
+ g_fp->_currentScene = oldsc;
+ }
+ }
+ }
+}
+
+void scene09_initScene(Scene *sc) {
+ g_vars->scene09_flyingBall = 0;
+ g_vars->scene09_var05 = 0;
+ g_vars->scene09_glotatel = sc->getStaticANIObject1ById(ANI_GLOTATEL, -1);
+ g_vars->scene09_spitter = sc->getStaticANIObject1ById(ANI_PLEVATEL, -1);
+ g_vars->scene09_grit = sc->getStaticANIObject1ById(ANI_GRIT_9, -1);
+ g_vars->scene09_var08 = 1;
+ g_vars->scene09_var09 = 0;
+ g_vars->scene09_var10 = -1;
+ g_vars->scene09_var11 = -1;
+ g_vars->scene09_var12 = -1000;
+
+ g_vars->scene09_balls.cPlexLen = 10;
+ g_vars->scene09_var07.cPlexLen = 10;
+
+ while (g_vars->scene09_balls.numBalls) {
+ Ball *b = g_vars->scene09_balls.pHead->p0;
+
+ g_vars->scene09_balls.pHead = g_vars->scene09_balls.pHead->p0;
+
+ if (g_vars->scene09_balls.pHead)
+ g_vars->scene09_balls.pHead->p0->p1 = 0;
+ else
+ g_vars->scene09_balls.field_8 = 0;
+
+ g_vars->scene09_balls.init(&b);
+ }
+
+ g_vars->scene09_var13 = 3;
+
+ g_vars->scene09_hangers.clear();
+ g_vars->scene09_var15 = 4;
+ g_vars->scene09_numMovingHangers = 4;
+
+ StaticANIObject *hanger = sc->getStaticANIObject1ById(ANI_VISUNCHIK, -1);
+ Hanger *hng = new Hanger;
+
+ hng->ani = hanger;
+ hng->phase = 0;
+ hng->field_4 = 0;
+ hng->field_8 = 0;
+
+ g_vars->scene09_hangers.push_back(hng);
+
+ int x = 75;
+
+ for (int i = 1; x < 300; i++, x += 75) {
+ StaticANIObject *ani = new StaticANIObject(hanger);
+
+ ani->show1(x + hanger->_ox, hanger->_oy, MV_VSN_CYCLE2, 0);
+ sc->addStaticANIObject(hanger, 1);
+
+ hng = new Hanger;
+
+ hng->ani = ani;
+ hng->phase = 0;
+ hng->field_4 = 0;
+ hng->field_8 = 0;
+
+ g_vars->scene09_hangers.push_back(hng);
+ }
+
+ while (g_vars->scene09_var07.numBalls) {
+ Ball *ohead = g_vars->scene09_var07.pHead;
+
+ g_vars->scene09_var07.pHead = g_vars->scene09_var07.pHead->p0;
+
+ if (g_vars->scene09_var07.pHead)
+ ohead->p0->p1 = 0;
+ else
+ g_vars->scene09_var07.field_8 = 0;
+
+ ohead->p0 = g_vars->scene09_var07.pTail;
+
+ g_vars->scene09_var07.pTail = ohead;
+
+ g_vars->scene09_var07.numBalls--;
+ }
+
+ g_vars->scene09_var07.reset();
+
+ Ball *b9 = g_vars->scene09_var07.sub04(g_vars->scene09_var07.field_8, 0);
+ b9->ani = sc->getStaticANIObject1ById(ANI_BALL9, -1);
+ b9->ani->setAlpha(0xc8);
+
+ if (g_vars->scene09_var07.field_8) {
+ g_vars->scene09_var07.field_8->p0 = b9;
+ g_vars->scene09_var07.field_8 = b9;
+ } else {
+ g_vars->scene09_var07.pHead = b9;
+ g_vars->scene09_var07.field_8 = b9;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ StaticANIObject *newball = new StaticANIObject(b9->ani);
+
+ newball->setAlpha(0xc8);
+
+ Ball *runPtr = g_vars->scene09_var07.pTail;
+ Ball *lastP = g_vars->scene09_var07.field_8;
+
+ if (!g_vars->scene09_var07.pTail) {
+ g_vars->scene09_var07.cPlex = (byte *)calloc(g_vars->scene09_var07.cPlexLen, sizeof(Ball));
+
+ byte *p1 = g_vars->scene09_var07.cPlex + (g_vars->scene09_var07.cPlexLen - 1) * sizeof(Ball);
+
+ if (g_vars->scene09_var07.cPlexLen - 1 < 0) {
+ runPtr = g_vars->scene09_var07.pTail;
+ } else {
+ runPtr = g_vars->scene09_var07.pTail;
+
+ for (int j = 0; j < g_vars->scene09_var07.cPlexLen; j++) {
+ ((Ball *)p1)->p1 = runPtr;
+ runPtr = (Ball *)p1;
+
+ p1 -= sizeof(Ball);
+ }
+
+ g_vars->scene09_var07.pTail = runPtr;
+ }
+ }
+
+ g_vars->scene09_var07.pTail = runPtr->p0;
+ runPtr->p1 = lastP;
+ runPtr->p0 = 0;
+ runPtr->ani = newball;
+
+ g_vars->scene09_var07.numBalls++;
+
+ if (g_vars->scene09_var07.field_8)
+ g_vars->scene09_var07.field_8->p0 = runPtr;
+ else
+ g_vars->scene09_var07.pHead = runPtr;
+
+ g_vars->scene09_var07.field_8 = runPtr;
+
+ sc->addStaticANIObject(newball, 1);
+ }
+
+ g_fp->setObjectState(sO_RightStairs_9, g_fp->getObjectEnumState(sO_RightStairs_9, sO_IsClosed));
+
+ GameVar *eggvar = g_fp->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_GulpedEggs);
+
+ g_vars->swallowedEgg1 = eggvar->getSubVarByName(sO_Egg1);
+ g_vars->swallowedEgg2 = eggvar->getSubVarByName(sO_Egg2);
+ g_vars->swallowedEgg3 = eggvar->getSubVarByName(sO_Egg3);
+
+ scene09_setupGrit(sc);
+
+ g_fp->initArcadeKeys("SC_9");
+
+ g_fp->lift_setButton(sO_Level1, ST_LBN_1N);
+
+ g_fp->setArcadeOverlay(PIC_CSR_ARCADE4);
+}
+
+int sceneHandler09_updateScreenCallback() {
+ int res = g_fp->drawArcadeOverlay(g_fp->_objectIdAtCursor == ANI_VISUNCHIK || g_vars->scene09_var10 >= 0);
+
+ if (!res)
+ g_fp->_updateScreenCallback = 0;
+
+ return res;
+}
+
+int scene09_updateCursor() {
+ g_fp->updateCursorCommon();
+
+ if (g_vars->scene09_var10 < 0) {
+ if (g_fp->_objectIdAtCursor == ANI_VISUNCHIK) {
+ if (g_fp->_cursorId == PIC_CSR_ITN)
+ g_fp->_updateScreenCallback = sceneHandler09_updateScreenCallback;
+ } else {
+ if (g_fp->_objectIdAtCursor == PIC_SC9_LADDER_R && g_fp->_cursorId == PIC_CSR_ITN)
+ g_fp->_cursorId = (g_vars->scene09_var02 < 350) ? PIC_CSR_GOD : PIC_CSR_GOU;
+ }
+ } else {
+ g_fp->_cursorId = PIC_CSR_ITN;
+ }
+
+ return g_fp->_cursorId;
+}
+
+void sceneHandler09_winArcade() {
+ if (g_vars->scene09_glotatel->_flags & 4) {
+ g_vars->scene09_glotatel->changeStatics2(ST_GLT_SIT);
+ g_vars->scene09_glotatel->startAnim(MV_GLT_FLYAWAY, 0, -1);
+
+ g_fp->setObjectState(sO_Jug, g_fp->getObjectEnumState(sO_Jug, sO_Unblocked));
+ g_fp->setObjectState(sO_RightStairs_9, g_fp->getObjectEnumState(sO_RightStairs_9, sO_IsOpened));
+
+ g_vars->scene09_var08 = 0;
+ }
+}
+
+void sceneHandler09_startAuntie() {
+ MessageQueue *mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_TTA9_GOL), 0, 1);
+
+ mq->getExCommandByIndex(0)->_x = g_fp->_sceneRect.right + 30;
+ mq->chain(0);
+}
+
+void sceneHandler09_spitterClick() {
+ if (g_vars->scene09_spitter->_flags & 4) {
+ PicAniInfo info;
+
+ g_vars->scene09_spitter->getPicAniInfo(&info);
+ g_vars->scene09_spitter->_messageQueueId = 0;
+ g_vars->scene09_spitter->changeStatics2(ST_PLV_SIT);
+
+ int x = g_vars->scene09_spitter->_ox - 10;
+ int y = g_vars->scene09_spitter->_oy + 145;
+
+ g_vars->scene09_spitter->setPicAniInfo(&info);
+
+ if (ABS(x - g_fp->_aniMan->_ox) > 1 || ABS(y - g_fp->_aniMan->_oy) > 1) {
+ MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, x, y, 1, ST_MAN_UP);
+
+ if (mq) {
+ ExCommand *ex = new ExCommand(0, 17, MSG_SC9_PLVCLICK, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags = 2;
+ mq->addExCommandToEnd(ex);
+
+ postExCommand(g_fp->_aniMan->_id, 2, x, y, 0, -1);
+ }
+ } else {
+ if (!g_fp->_aniMan->_movement) {
+ g_vars->scene09_spitter->changeStatics2(ST_PLV_SIT);
+ g_vars->scene09_spitter->hide();
+
+ g_fp->_aniMan->startAnim(MV_MAN9_SHOOT, 0, -1);
+
+ g_fp->stopAllSoundInstances(SND_9_006);
+ }
+
+ g_fp->_aniMan2 = 0;
+
+ if (g_fp->_sceneRect.left < 800)
+ g_fp->_currentScene->_x = 800 - g_fp->_sceneRect.left;
+ }
+ }
+}
+
+void sceneHandler09_eatBall() {
+ warning("STUB: sceneHandler09_eatBall()");
+}
+
+void sceneHandler09_showBall() {
+ warning("STUB: sceneHandler09_showBall()");
+}
+
+void sceneHandler09_cycleHangers() {
+ warning("STUB: sceneHandler09_cycleHangers()");
+}
+
+void sceneHandler09_limitHangerPhase() {
+ warning("STUB: sceneHandler09_limitHangerPhase()");
+}
+
+void sceneHandler09_checkHangerCollide() {
+ warning("STUB: sceneHandler09_checkHangerCollide()");
+}
+
+void sceneHandler09_hangerStartCycle() {
+ warning("STUB: sceneHandler09_hangerStartCycle()");
+}
+
+int sceneHandler09(ExCommand *cmd) {
+ if (cmd->_messageKind != 17)
+ return 0;
+
+ switch (cmd->_messageNum) {
+ case MSG_CMN_WINARCADE:
+ sceneHandler09_winArcade();
+ break;
+
+ case MSG_SC9_STARTTIOTIA:
+ sceneHandler09_startAuntie();
+ break;
+
+ case MSG_SC9_FROMLADDER:
+ getCurrSceneSc2MotionController()->setEnabled();
+ getGameLoaderInteractionController()->enableFlag24();
+
+ g_vars->scene09_var09 = 0;
+ break;
+
+ case MSG_SC9_TOLADDER:
+ getCurrSceneSc2MotionController()->clearEnabled();
+ getGameLoaderInteractionController()->disableFlag24();
+
+ g_vars->scene09_var09 = 1;
+ break;
+
+ case MSG_SC9_PLVCLICK:
+ sceneHandler09_spitterClick();
+ break;
+
+ case MSG_SC9_FLOWN:
+ g_vars->scene09_var08 = 0;
+ break;
+
+ case MSG_SC9_EATBALL:
+ sceneHandler09_eatBall();
+ break;
+
+ case MSG_SC9_SHOWBALL:
+ sceneHandler09_showBall();
+ break;
+
+ case 33:
+ {
+ int res = 0;
+
+ if (g_fp->_aniMan2) {
+ int x = g_fp->_aniMan2->_ox;
+
+ g_vars->scene09_var02 = g_fp->_aniMan2->_oy;
+
+ if (x < g_fp->_sceneRect.left + 200)
+ g_fp->_currentScene->_x = x - g_fp->_sceneRect.left - 300;
+
+ if (x > g_fp->_sceneRect.right - 200)
+ g_fp->_currentScene->_x = x - g_fp->_sceneRect.right + 300;
+
+ res = 1;
+ } else {
+ if (g_fp->_aniMan->_movement && g_fp->_aniMan->_movement->_id != MV_MAN9_SHOOT)
+ g_fp->_aniMan2 = g_fp->_aniMan;
+ }
+
+ sceneHandler09_cycleHangers();
+ sceneHandler09_limitHangerPhase();
+ sceneHandler09_checkHangerCollide();
+
+ if (g_vars->scene09_var10 >= 0)
+ sceneHandler09_hangerStartCycle();
+
+ if (!g_vars->scene09_var17)
+ g_fp->_behaviorManager->updateBehaviors();
+
+ g_fp->startSceneTrack();
+
+ return res;
+ }
+
+ case 30:
+ if (g_vars->scene09_var10 >= 0) {
+ if (ABS(g_vars->scene09_hangers[g_vars->scene09_var10]->phase) < 15) {
+ g_vars->scene09_hangers[g_vars->scene09_var10]->ani->_callback2 = 0;
+ g_vars->scene09_hangers[g_vars->scene09_var10]->ani->changeStatics2(ST_VSN_NORMAL);
+ }
+ }
+
+ g_vars->scene09_var10 = -1;
+
+ break;
+
+ case 29:
+ {
+ StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y);
+
+ if (ani) {
+ if (ani->_id == ANI_PLEVATEL) {
+ sceneHandler09_spitterClick();
+ break;
+ }
+
+ if (ani->_id == ANI_VISUNCHIK) {
+ if (g_vars->scene09_numMovingHangers > 0) {
+ int hng = 0;
+
+ while (g_vars->scene09_hangers[hng]->ani != ani) {
+ ++hng;
+
+ if (hng >= g_vars->scene09_numMovingHangers)
+ break;
+ }
+
+ g_vars->scene09_var10 = hng;
+ g_vars->scene09_var11 = g_vars->scene09_hangers[hng]->phase;
+ g_vars->scene09_var12 = g_vars->scene09_hangers[hng]->phase;
+
+ g_vars->scene09_var19 = cmd->_y;
+
+ if (!g_vars->scene09_hangers[hng]->ani->_movement || g_vars->scene09_hangers[hng]->ani->_movement->_id != MV_VSN_CYCLE2) {
+ g_vars->scene09_hangers[hng]->ani->changeStatics2(ST_VSN_NORMAL);
+ g_vars->scene09_hangers[hng]->ani->startAnim(MV_VSN_CYCLE2, 0, -1);
+ g_vars->scene09_hangers[hng]->ani->_callback2 = 0;
+ }
+
+ ExCommand *ex = new ExCommand(0, 35, SND_9_018, 0, 0, 0, 1, 0, 0, 0);
+
+ ex->_field_14 = 1;
+ ex->_excFlags |= 2;
+ ex->postMessage();
+ }
+
+ break;
+ }
+ }
+
+ if (g_vars->scene09_var09 && g_fp->_currentScene->getPictureObjectIdAtPos(cmd->_sceneClickX, cmd->_sceneClickY) == PIC_SC9_LADDER_R
+ && !cmd->_keyCode && !g_fp->_aniMan->_movement) {
+ handleObjectInteraction(g_fp->_aniMan, g_fp->_currentScene->getPictureObjectById(PIC_SC9_LADDER_R, 0), 0);
+ }
+
+ if (!ani || !canInteractAny(g_fp->_aniMan, ani, cmd->_keyCode)) {
+ int picId = g_fp->_currentScene->getPictureObjectIdAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
+ PictureObject *pic = g_fp->_currentScene->getPictureObjectById(picId, 0);
+
+ if (!pic || !canInteractAny(g_fp->_aniMan, pic, cmd->_keyCode)) {
+ if ((g_fp->_sceneRect.right - cmd->_sceneClickX < 47 && g_fp->_sceneRect.right < g_fp->_sceneWidth - 1) || (cmd->_sceneClickX - g_fp->_sceneRect.left < 47 && g_fp->_sceneRect.left > 0))
+ g_fp->processArcade(cmd);
+ }
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/scene10.cpp b/engines/fullpipe/scenes/scene10.cpp
index 9c00902bba..4f9e627fa4 100644
--- a/engines/fullpipe/scenes/scene10.cpp
+++ b/engines/fullpipe/scenes/scene10.cpp
@@ -170,7 +170,7 @@ int sceneHandler10(ExCommand *ex) {
break;
case 64:
- g_fp->lift_sub05(ex);
+ g_fp->lift_hoverButton(ex);
break;
case 29:
@@ -185,7 +185,7 @@ int sceneHandler10(ExCommand *ex) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
ex->_messageKind = 0;
return 0;
diff --git a/engines/fullpipe/scenes/scene14.cpp b/engines/fullpipe/scenes/scene14.cpp
index ab0487974a..28f054fd32 100644
--- a/engines/fullpipe/scenes/scene14.cpp
+++ b/engines/fullpipe/scenes/scene14.cpp
@@ -749,7 +749,7 @@ int sceneHandler14(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case 33:
@@ -820,7 +820,7 @@ int sceneHandler14(ExCommand *cmd) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
break;
}
diff --git a/engines/fullpipe/scenes/scene15.cpp b/engines/fullpipe/scenes/scene15.cpp
index 155897619f..9e11df92e4 100644
--- a/engines/fullpipe/scenes/scene15.cpp
+++ b/engines/fullpipe/scenes/scene15.cpp
@@ -156,7 +156,7 @@ int sceneHandler15(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case 29:
@@ -171,7 +171,7 @@ int sceneHandler15(ExCommand *cmd) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
}
diff --git a/engines/fullpipe/scenes/scene27.cpp b/engines/fullpipe/scenes/scene27.cpp
new file mode 100644
index 0000000000..8623b2b9b3
--- /dev/null
+++ b/engines/fullpipe/scenes/scene27.cpp
@@ -0,0 +1,759 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+
+#include "fullpipe/objectnames.h"
+#include "fullpipe/constants.h"
+
+#include "fullpipe/gameloader.h"
+#include "fullpipe/motion.h"
+#include "fullpipe/scenes.h"
+#include "fullpipe/statics.h"
+
+#include "fullpipe/interaction.h"
+#include "fullpipe/behavior.h"
+
+#define DBG 0
+
+namespace Fullpipe {
+
+struct Bat {
+ StaticANIObject *ani;
+ int field_4;
+ double power;
+ double field_10;
+ double currX;
+ double currY;
+ double powerCos;
+ double powerSin;
+};
+
+void scene27_initScene(Scene *sc) {
+ g_vars->scene27_hitZone = sc->getPictureObjectById(PIC_SC27_HITZONE2, 0);
+ g_vars->scene27_driver = sc->getStaticANIObject1ById(ANI_VODILLA, -1);
+ g_vars->scene27_maid = sc->getStaticANIObject1ById(ANI_MAID, -1);
+ g_vars->scene27_batHandler = sc->getStaticANIObject1ById(ANI_BITAHANDLER, -1);
+
+ g_vars->scene27_balls.numBalls = 0;
+ g_vars->scene27_balls.pTail = 0;
+ g_vars->scene27_balls.field_8 = 0;
+ g_vars->scene27_balls.pHead = 0;
+ g_vars->scene27_balls.cPlexLen = 10;
+
+ free(g_vars->scene27_balls.cPlex);
+ g_vars->scene27_balls.cPlex = 0;
+
+ g_vars->scene27_bats.clear();
+ g_vars->scene27_var07.clear();
+
+ g_vars->scene27_driverHasVent = true;
+ g_vars->scene27_bat = sc->getStaticANIObject1ById(ANI_BITA, -1);
+
+ for (int i = 0; i < 4; i++) {
+ StaticANIObject *newbat = new StaticANIObject(g_vars->scene27_bat);
+
+ Ball *runPtr = g_vars->scene27_balls.pTail;
+ Ball *lastP = g_vars->scene27_balls.field_8;
+
+ if (!g_vars->scene27_balls.pTail) {
+ g_vars->scene27_balls.cPlex = (byte *)calloc(g_vars->scene27_balls.cPlexLen, sizeof(Ball));
+
+ byte *p1 = g_vars->scene27_balls.cPlex + (g_vars->scene27_balls.cPlexLen - 1) * sizeof(Ball);
+
+ if (g_vars->scene27_balls.cPlexLen - 1 < 0) {
+ runPtr = g_vars->scene27_balls.pTail;
+ } else {
+ runPtr = g_vars->scene27_balls.pTail;
+
+ for (int j = 0; j < g_vars->scene27_balls.cPlexLen; j++) {
+ ((Ball *)p1)->p1 = runPtr;
+ runPtr = (Ball *)p1;
+
+ p1 -= sizeof(Ball);
+ }
+
+ g_vars->scene27_balls.pTail = runPtr;
+ }
+ }
+
+ g_vars->scene27_balls.pTail = runPtr->p0;
+ runPtr->p1 = lastP;
+ runPtr->p0 = 0;
+ runPtr->ani = newbat;
+
+ g_vars->scene27_balls.numBalls++;
+
+ if (g_vars->scene27_balls.field_8)
+ g_vars->scene27_balls.field_8->p0 = runPtr;
+ else
+ g_vars->scene27_balls.pHead = runPtr;
+
+ g_vars->scene27_balls.field_8 = runPtr;
+
+ sc->addStaticANIObject(newbat, 1);
+ }
+
+ g_vars->scene27_dudeIsAiming = false;
+ g_vars->scene27_maxPhaseReached = false;
+ g_vars->scene27_wipeIsNeeded = false;
+ g_vars->scene27_driverPushedButton = false;
+ g_vars->scene27_numLostBats = 0;
+ g_vars->scene27_knockCount = 0;
+ g_vars->scene27_launchPhase = 0;
+
+ Scene *oldsc = g_fp->_currentScene;
+ g_fp->_currentScene = sc;
+
+ if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) {
+ g_vars->scene27_maid->changeStatics2(ST_MID_SWAB2);
+ } else if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithBroom)) {
+ g_vars->scene27_maid->changeStatics2(ST_MID_BROOM);
+ } else if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSpade)) {
+ g_vars->scene27_maid->changeStatics2(ST_MID_SPADE);
+ }
+
+ g_fp->_currentScene = oldsc;
+
+ g_fp->setArcadeOverlay(PIC_CSR_ARCADE7);
+}
+
+int scene27_updateCursor() {
+ g_fp->updateCursorCommon();
+
+ if (g_vars->scene27_dudeIsAiming) {
+ if (g_fp->_cursorId != PIC_CSR_DEFAULT_INV && g_fp->_cursorId != PIC_CSR_ITN_INV)
+ g_fp->_cursorId = PIC_CSR_ARCADE7_D;
+
+ } else if (g_fp->_objectIdAtCursor == ANI_MAN) {
+ if (g_vars->scene27_maxPhaseReached)
+ if (g_fp->_cursorId == PIC_CSR_DEFAULT)
+ g_fp->_cursorId = PIC_CSR_ITN;
+ }
+
+ return g_fp->_cursorId;
+}
+
+void sceneHandler27_driverGiveVent() {
+ g_vars->scene27_driver->changeStatics2(ST_DRV_VENT);
+ g_vars->scene27_driver->startMQIfIdle(QU_DRV_GIVEVENT, 1);
+
+ g_vars->scene27_driverHasVent = false;
+
+ getCurrSceneSc2MotionController()->setEnabled();
+ getGameLoaderInteractionController()->enableFlag24();
+
+ g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
+}
+
+void sceneHandler27_winArcade() {
+ if (g_fp->getObjectState(sO_Driver) == g_fp->getObjectEnumState(sO_Driver, sO_WithSteering)) {
+ g_vars->scene27_dudeIsAiming = false;
+
+ g_fp->_aniMan->_callback2 = 0;
+ g_fp->_aniMan->changeStatics2(ST_MAN_RIGHT);
+
+ sceneHandler27_driverGiveVent();
+ }
+}
+
+void sceneHandler27_takeVent() {
+ if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) {
+ if (g_vars->scene27_maid->isIdle()) {
+ if (g_vars->scene27_maid->_flags & 4) {
+ g_vars->scene27_maid->changeStatics2(ST_MID_SWAB2);
+ g_vars->scene27_maid->startMQIfIdle(QU_MID_CLEANVENT, 1);
+ }
+ }
+ }
+}
+
+void sceneHandler27_showNextBat() {
+ if (g_vars->scene27_bat) {
+ MessageQueue *mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC27_SHOWBET), 0, 1);
+
+ mq->replaceKeyCode(-1, g_vars->scene27_bat->_okeyCode);
+ mq->chain(0);
+ }
+
+ g_vars->scene27_batHandler->_priority = 1045;
+}
+
+int sceneHandler27_updateScreenCallback() {
+ int res;
+
+ res = g_fp->drawArcadeOverlay(getGameLoaderInteractionController()->_flag24 == 0);
+
+ if (!res)
+ g_fp->_updateScreenCallback = 0;
+
+ return res;
+}
+
+void sceneHandler27_aniManCallback(int *phase) {
+ if (!g_vars->scene27_maxPhaseReached) {
+ if (*phase >= 5)
+ g_vars->scene27_maxPhaseReached = true;
+ else
+ ++*phase;
+ }
+}
+
+void sceneHandler27_throwBat() {
+ if (getGameLoaderInteractionController()->_flag24)
+ g_fp->_updateScreenCallback = sceneHandler27_updateScreenCallback;
+
+ g_fp->_aniMan->_callback2 = sceneHandler27_aniManCallback;
+
+ g_fp->_aniMan->startAnim(MV_MAN27_THROWBET, 0, -1);
+
+ getCurrSceneSc2MotionController()->clearEnabled();
+ getGameLoaderInteractionController()->disableFlag24();
+
+ g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
+
+ g_vars->scene27_maxPhaseReached = false;
+
+ g_vars->scene27_bat->hide();
+}
+
+void sceneHandler27_clickBat(ExCommand *cmd) {
+ int bx = g_vars->scene27_bat->_ox - 5;
+ int by = g_vars->scene27_bat->_oy - 71;
+
+#if DBG
+ sceneHandler27_throwBat();
+ return;
+#endif
+
+ if (ABS(bx - g_fp->_aniMan->_ox) > 1 || ABS(by - g_fp->_aniMan->_oy) > 1
+ || g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) {
+ MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, bx, by, 1, ST_MAN_RIGHT);
+
+ if (mq) {
+ mq->addExCommandToEnd(cmd->createClone());
+
+ postExCommand(g_fp->_aniMan->_id, 2, bx, by, 0, -1);
+ }
+ } else {
+ sceneHandler27_throwBat();
+ }
+}
+
+void sceneHandler27_maidSwab() {
+#if DBG
+ return;
+#endif
+ if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab))
+ g_vars->scene27_maid->changeStatics2(ST_MID_SWAB);
+}
+
+void sceneHandler27_startBat(StaticANIObject *bat) {
+ Bat *newbat = new Bat;
+
+ newbat->power = g_vars->scene27_launchPhase * 2.5 + 8.0;
+ newbat->field_10 = 0;
+ newbat->ani = bat;
+ newbat->powerCos = newbat->power * cos(0.0);
+ newbat->powerSin = newbat->power * sin(0.0);
+ newbat->currX = newbat->powerCos + (double)g_fp->_aniMan->_ox + 42.0;
+ newbat->currY = newbat->powerSin + (double)g_fp->_aniMan->_oy + 58.0;
+
+ bat->_statics = (Statics *)bat->_staticsList[0];
+ bat->setOXY((int)newbat->currX, (int)newbat->currY);
+ bat->_flags |= 4;
+
+ g_vars->scene27_bats.push_back(newbat);
+
+ sceneHandler27_maidSwab();
+}
+
+void sceneHandler27_startAiming() {
+ g_vars->scene27_dudeIsAiming = false;
+ g_vars->scene27_maxPhaseReached = false;
+
+ g_fp->_aniMan->_callback2 = 0;
+
+ g_vars->scene27_launchPhase = g_fp->_aniMan->_movement->_currDynamicPhaseIndex - 6;
+
+ int phase = 21 - g_vars->scene27_launchPhase;
+
+ if (phase < 14)
+ phase = 14;
+
+ if (phase > 20)
+ phase = 20;
+
+ g_fp->playSound(SND_27_044, 0);
+
+ g_fp->_aniMan->_movement->setDynamicPhaseIndex(phase);
+}
+
+void sceneHandler27_initAiming(ExCommand *cmd) {
+ g_vars->scene27_aimStartX = cmd->_x;
+ g_vars->scene27_aimStartY = cmd->_y;
+ g_vars->scene27_dudeIsAiming = true;
+ g_vars->scene27_maxPhaseReached = false;
+}
+
+void sceneHandler27_aimDude() {
+ int phase = (g_vars->scene27_aimStartX - g_fp->_mouseScreenPos.x) / 20 + 6;
+
+ if (phase < 6)
+ phase = 6;
+
+ if (phase > 11)
+ phase = 11;
+
+ if (g_fp->_aniMan->_movement)
+ g_fp->_aniMan->_movement->setDynamicPhaseIndex(phase);
+}
+
+void sceneHandler27_wipeDo() {
+ for (uint i = 0; i < g_vars->scene27_bats.size(); i++) {
+ if (g_vars->scene27_bats[i]->currX < 800.0) {
+ g_vars->scene27_bats[i]->field_10 = atan2(800.0 - g_vars->scene27_bats[i]->currX, 520.0 - g_vars->scene27_bats[i]->currY);
+ g_vars->scene27_bats[i]->power += 1.0;
+ }
+ }
+}
+
+bool sceneHandler27_batFallLogic(int batn) {
+ Bat *bat = g_vars->scene27_bats[batn];
+
+ int y = (bat->currY - 458.0) * 0.4848484848484849 + 734.0;
+
+ if (y >= bat->currX)
+ return false;
+
+ if (bat->currX - y > 15.0 || bat->ani->_statics->_staticsId == ST_BTA_FALL) {
+ bat->ani->_priority = 2020;
+
+ g_vars->scene27_var07.push_back(bat);
+
+ if (batn != g_vars->scene27_var07.size() - 1)
+ g_vars->scene27_var07.remove_at(batn);
+ } else if (!bat->ani->_movement) {
+ bat->ani->startAnim(MV_BTA_FALL, 0, -1);
+ }
+
+ return true;
+}
+
+bool sceneHandler27_batCalcDistance(int bat1, int bat2) {
+ double at = atan2(g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX, g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY);
+ double dy = g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY;
+ double dx = g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX;
+ double ay = cos(at);
+ double ax = sin(at);
+
+ return sqrt(ax * ax * 0.25 + ay * ay) * 54.0 > sqrt(dx * dx + dy * dy);
+}
+
+void sceneHandler27_knockBats(int bat1n, int bat2n) {
+ Bat *bat1 = g_vars->scene27_bats[bat1n];
+ Bat *bat2 = g_vars->scene27_bats[bat2n];
+
+ if (0.0 != bat1->power) {
+ double rndF = (double)g_fp->_rnd->getRandomNumber(32767) * 0.0000009155552842799158 - 0.015
+ + atan2(bat2->currX - bat1->currX, bat2->currY - bat1->currY);
+ double rndCos = cos(rndF);
+ double rndSin = sin(rndF);
+
+ double pow1x = cos(bat1->field_10 - rndF) * (double)((int)(bat2->currX - bat1->currX) >= 0 ? 1 : -1) * bat1->power;
+ double pow1y = sin(bat1->field_10 - rndF) * (double)((int)(bat2->currY - bat1->currY) >= 0 ? 1 : -1) * bat1->power;
+
+ bat1->powerCos -= pow1x * 1.1;
+ bat1->powerSin -= pow1y * 1.1;
+
+ rndF = ((double)g_fp->_rnd->getRandomNumber(32767) * 0.0000009155552842799158 - 0.015
+ + atan2(bat1->currX - bat2->currX, bat1->currY - bat2->currY));
+ double pow2x = cos(bat2->field_10 - rndF) * (double)((int)(bat1->currX - bat2->currX) >= 0 ? 1 : -1) * bat2->power;
+ double pow2y = sin(bat2->field_10 - rndF) * (double)((int)(bat1->currY - bat2->currY) >= 0 ? 1 : -1) * bat2->power;
+
+ bat2->powerCos -= pow2x * 1.1;
+ bat2->powerSin -= pow2y * 1.1;
+
+ double dy = bat1->currY - bat2->currY;
+ double dx = bat1->currX - bat2->currX;
+ double dist = (sqrt(rndSin * rndSin * 0.25 + rndCos * rndCos) * 54.0 - sqrt(dx * dx + dy * dy)) / cos(rndF - bat1->field_10);
+ bat1->currX -= cos(bat1->field_10) * (dist + 1.0);
+ bat1->currY -= sin(bat1->field_10) * (dist + 1.0);
+ bat1->powerCos += pow2x * 0.64;
+
+ if (bat1->currX <= 500.0)
+ bat1->powerSin = 0.0;
+ else
+ bat1->powerSin += pow2y * 0.64;
+
+ bat1->field_10 = atan2(bat1->powerCos, bat1->powerSin);
+ bat1->power = sqrt(bat1->powerCos * bat1->powerCos + bat1->powerSin * bat1->powerSin);
+ bat2->powerCos += pow1x * 0.64;
+
+ if (bat2->currX <= 500.0)
+ bat2->powerSin = 0;
+ else
+ bat2->powerSin += pow1y * 0.64;
+
+ bat2->field_10 = atan2(bat2->powerCos, bat2->powerSin);
+ bat2->power = sqrt(bat2->powerCos * bat2->powerCos + bat2->powerSin * bat2->powerSin);
+
+ g_fp->playSound(SND_27_026, 0);
+ }
+}
+
+void sceneHandler27_batSetColors(int batn) {
+ Bat *bat = g_vars->scene27_bats[batn];
+
+ if (g_vars->scene27_hitZone->isPixelHitAtPos((int)bat->currX, (int)bat->currY) ) {
+ if (bat->ani->_statics->_staticsId == ST_BTA_NORM) {
+ if (!bat->ani->_movement)
+ bat->ani->_statics = bat->ani->getStaticsById(ST_BTA_HILITE);
+ }
+ } else {
+ if (bat->ani->_statics->_staticsId == ST_BTA_HILITE) {
+ if (!bat->ani->_movement)
+ bat->ani->_statics = bat->ani->getStaticsById(ST_BTA_NORM);
+ }
+ }
+}
+
+void sceneHandler27_driverPushButton() {
+ if (g_fp->getObjectState(sO_Driver) == g_fp->getObjectEnumState(sO_Driver, sO_WithSteering)) {
+ g_vars->scene27_driver->changeStatics2(ST_DRV_VENT);
+ chainQueue(QU_DRV_PUSHBUTTON, 1);
+
+ g_vars->scene27_driverPushedButton = true;
+ } else {
+ g_vars->scene27_driver->changeStatics2(ST_DRV_SITNOVENT);
+
+
+ chainQueue(QU_DRV_PUSHBUTTON_NOVENT, 1);
+
+ g_vars->scene27_driverPushedButton = true;
+ }
+}
+
+void sceneHandler27_maidSwitchback() {
+#ifndef DBG
+ if (g_fp->getObjectState(sO_Maid) == g_fp->getObjectEnumState(sO_Maid, sO_WithSwab)) {
+ g_vars->scene27_maid->changeStatics2(ST_MID_SWAB);
+ g_vars->scene27_maid->startMQIfIdle(QU_MID_SWITCHBACK, 1);
+ }
+#endif
+}
+
+void sceneHandler27_batLogic() {
+ if (g_vars->scene27_balls.numBalls) {
+ g_vars->scene27_bat = g_vars->scene27_balls.pHead->ani;
+
+ g_vars->scene27_balls.pHead = g_vars->scene27_balls.pHead->p0;
+
+ if (g_vars->scene27_balls.pHead)
+ g_vars->scene27_balls.pHead->p0->p1 = 0;
+ else
+ g_vars->scene27_balls.field_8 = 0;
+
+ g_vars->scene27_balls.init(&g_vars->scene27_balls.pHead->p0);
+
+ int mv;
+
+ switch (g_vars->scene27_batHandler->_statics->_staticsId) {
+ case ST_BTH_5:
+ mv = MV_BTH_5_4;
+ break;
+
+ case ST_BTH_4:
+ mv = MV_BTH_4_3;
+ break;
+
+ case ST_BTH_3:
+ mv = MV_BTH_3_2;
+ break;
+
+ case ST_BTH_2:
+ mv = MV_BTH_2_1;
+ break;
+
+ case ST_BTH_1:
+ mv = MV_BTH_1_0;
+ break;
+
+ default:
+ chainQueue(QU_SC27_RESTARTBETS, 1);
+
+ getCurrSceneSc2MotionController()->setEnabled();
+ getGameLoaderInteractionController()->enableFlag24();
+
+ g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
+
+ return;
+ }
+
+ MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact());
+
+ mq->setFlags(mq->getFlags() | 1);
+
+ ExCommand *ex = new ExCommand(g_vars->scene27_batHandler->_id, 1, mv, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 2;
+ mq->addExCommandToEnd(ex);
+
+ ex = new ExCommand(0, 17, MSG_SC27_CLICKBET, 0, 0, 0, 1, 0, 0, 0);
+ ex->_excFlags |= 3;
+ mq->addExCommandToEnd(ex);
+
+ mq->chain(0);
+ } else {
+ g_vars->scene27_bat = 0;
+ }
+}
+
+void sceneHandler27_calcWinArcade() {
+ if (!g_vars->scene27_wipeIsNeeded && !g_vars->scene27_driverPushedButton) {
+ int numHilite = 0;
+
+ for (uint i = 0; i < g_vars->scene27_bats.size(); i++) {
+ if (g_vars->scene27_bats[i]->ani->_statics->_staticsId == ST_BTA_HILITE)
+ numHilite++;
+ }
+
+ if (numHilite >= 3) {
+ if (g_fp->getObjectState(sO_Driver) == g_fp->getObjectEnumState(sO_Driver, sO_WithSteering)) {
+ sceneHandler27_driverGiveVent();
+ sceneHandler27_maidSwitchback();
+
+ return;
+ }
+ }
+
+ if (!g_vars->scene27_balls.numBalls) {
+ sceneHandler27_driverPushButton();
+ sceneHandler27_maidSwitchback();
+ return;
+ }
+
+ sceneHandler27_batLogic();
+ }
+
+ sceneHandler27_maidSwitchback();
+}
+
+void sceneHandler27_regenBats() {
+ g_vars->scene27_wipeIsNeeded = false;
+
+ for (uint i = 0; i < g_vars->scene27_var07.size(); i++) {
+ g_vars->scene27_var07[i]->ani->hide();
+
+ Ball *runPtr = g_vars->scene27_balls.pTail;
+ Ball *lastP = g_vars->scene27_balls.field_8;
+ StaticANIObject *newbat = g_vars->scene27_var07[i]->ani;
+
+ if (!g_vars->scene27_balls.pTail) {
+ g_vars->scene27_balls.cPlex = (byte *)calloc(g_vars->scene27_balls.cPlexLen, sizeof(Ball));
+
+ byte *p1 = g_vars->scene27_balls.cPlex + (g_vars->scene27_balls.cPlexLen - 1) * sizeof(Ball);
+
+ if (g_vars->scene27_balls.cPlexLen - 1 < 0) {
+ runPtr = g_vars->scene27_balls.pTail;
+ } else {
+ runPtr = g_vars->scene27_balls.pTail;
+
+ for (int j = 0; j < g_vars->scene27_balls.cPlexLen; j++) {
+ ((Ball *)p1)->p1 = runPtr;
+ runPtr = (Ball *)p1;
+
+ p1 -= sizeof(Ball);
+ }
+
+ g_vars->scene27_balls.pTail = runPtr;
+ }
+ }
+
+ g_vars->scene27_balls.pTail = runPtr->p0;
+ runPtr->p1 = lastP;
+ runPtr->p0 = 0;
+ runPtr->ani = newbat;
+
+ g_vars->scene27_balls.numBalls++;
+
+ if (g_vars->scene27_balls.field_8)
+ g_vars->scene27_balls.field_8->p0 = runPtr;
+ else
+ g_vars->scene27_balls.pHead = runPtr;
+
+ g_vars->scene27_balls.field_8 = runPtr;
+ }
+
+ g_vars->scene27_var07.clear();
+
+ sceneHandler27_batLogic();
+
+ g_vars->scene27_driverPushedButton = false;
+}
+
+void sceneHandler27_animateBats() {
+ int oldCount = g_vars->scene27_knockCount;
+
+ g_vars->scene27_numLostBats = 0;
+ g_vars->scene27_knockCount = 0;
+
+ for (uint i = 0; i < g_vars->scene27_bats.size(); i++) {
+ Bat *bat = g_vars->scene27_bats[i];
+
+ bat->currX = cos(bat->field_10) * bat->power + bat->currX;
+ bat->currY = sin(bat->field_10) * bat->power + bat->currY;
+
+ bat->ani->setOXY((int)bat->currX, (int)bat->currY);
+ bat->ani->_priority = (int)(600.0 - bat->currY);
+
+ double powerDelta;
+
+ if (cos(bat->field_10) >= 0.0 || bat->currX >= 362.0)
+ powerDelta = bat->power * 0.035;
+ else
+ powerDelta = bat->power * 0.4;
+
+ bat->power -= powerDelta;
+ bat->powerCos = cos(bat->field_10) * bat->power;
+ bat->powerSin = sin(bat->field_10) * bat->power;
+
+ if (bat->power >= 0.5)
+ g_vars->scene27_knockCount++;
+ else
+ bat->power = 0;
+
+ sceneHandler27_batSetColors(i);
+
+ if (!sceneHandler27_batFallLogic(i) && !g_vars->scene27_wipeIsNeeded) {
+ for (uint j = 0; j < g_vars->scene27_bats.size(); j++) {
+ if (i != j && sceneHandler27_batCalcDistance(i, j))
+ sceneHandler27_knockBats(i, j);
+ }
+ }
+ }
+
+ for (uint i = 0; i < g_vars->scene27_var07.size(); i++) {
+ Bat *bat = g_vars->scene27_var07[i];
+
+ if (bat->currY >= 700.0) {
+ g_vars->scene27_numLostBats++;
+ } else {
+ bat->currX = bat->powerCos + bat->currX;
+ bat->currY = bat->powerSin + bat->currY;
+ bat->ani->setOXY((int)bat->currX, (int)bat->currY);
+ bat->powerSin = bat->powerSin + 1.0;
+ }
+ }
+
+ if (oldCount != g_vars->scene27_knockCount && !g_vars->scene27_knockCount)
+ sceneHandler27_calcWinArcade();
+
+ if (g_vars->scene27_wipeIsNeeded) {
+ if (g_vars->scene27_numLostBats == 5)
+ sceneHandler27_regenBats();
+ }
+}
+
+int sceneHandler27(ExCommand *cmd) {
+ if (cmd->_messageKind != 17)
+ return 0;
+
+ switch (cmd->_messageNum) {
+ case MSG_CMN_WINARCADE:
+ sceneHandler27_winArcade();
+ break;
+
+ case MSG_SC27_TAKEVENT:
+ sceneHandler27_takeVent();
+ break;
+
+ case MSG_SC27_SHOWNEXTBET:
+ sceneHandler27_showNextBat();
+ break;
+
+ case MSG_SC27_HANDLERTOFRONT:
+ g_vars->scene27_batHandler->_priority = 1005;
+ break;
+
+ case MSG_SC27_STARTWIPE:
+ g_vars->scene27_wipeIsNeeded = true;
+
+ g_fp->playSound(SND_27_027, 0);
+
+ break;
+
+ case MSG_SC27_CLICKBET:
+ sceneHandler27_clickBat(cmd);
+ break;
+
+ case MSG_SC27_STARTBET:
+ if (g_vars->scene27_bat)
+ sceneHandler27_startBat(g_vars->scene27_bat);
+
+ break;
+
+ case 30:
+ if (g_vars->scene27_dudeIsAiming)
+ sceneHandler27_startAiming();
+
+ break;
+
+ case 29:
+ if (g_fp->_aniMan == g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y)
+ && g_vars->scene27_maxPhaseReached)
+ sceneHandler27_initAiming(cmd);
+
+ break;
+
+ case 33:
+ if (g_fp->_aniMan2) {
+ int x = g_fp->_aniMan2->_ox;
+
+ if (x < g_fp->_sceneRect.left + 200)
+ g_fp->_currentScene->_x = x - 300 - g_fp->_sceneRect.left;
+
+ if (x > g_fp->_sceneRect.right - 200)
+ g_fp->_currentScene->_x = x + 300 - g_fp->_sceneRect.right;
+ }
+
+ if (g_vars->scene27_dudeIsAiming)
+ sceneHandler27_aimDude();
+
+ if (g_vars->scene27_wipeIsNeeded) {
+ sceneHandler27_wipeDo();
+
+ if (!g_fp->_aniMan->_movement && g_fp->_aniMan->_statics->_staticsId == ST_MAN_RIGHT)
+ g_fp->_aniMan->startAnim(MV_MAN27_FLOW, 0, -1);
+ }
+
+ sceneHandler27_animateBats();
+
+ g_fp->_behaviorManager->updateBehaviors();
+ g_fp->startSceneTrack();
+
+ break;
+ }
+
+ return 0;
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/scenes/scene30.cpp b/engines/fullpipe/scenes/scene30.cpp
index a807e692a7..39a51deeef 100644
--- a/engines/fullpipe/scenes/scene30.cpp
+++ b/engines/fullpipe/scenes/scene30.cpp
@@ -111,7 +111,7 @@ int sceneHandler30(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case MSG_LIFT_GO:
@@ -123,7 +123,7 @@ int sceneHandler30(ExCommand *cmd) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
}
diff --git a/engines/fullpipe/scenes/scene32.cpp b/engines/fullpipe/scenes/scene32.cpp
index 597d3422f6..be7c983277 100644
--- a/engines/fullpipe/scenes/scene32.cpp
+++ b/engines/fullpipe/scenes/scene32.cpp
@@ -339,7 +339,7 @@ int sceneHandler32(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case MSG_SC6_INSTHANDLE:
@@ -403,7 +403,7 @@ int sceneHandler32(ExCommand *cmd) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
break;
diff --git a/engines/fullpipe/scenes/scene34.cpp b/engines/fullpipe/scenes/scene34.cpp
index b3e0db75af..0e690f4703 100644
--- a/engines/fullpipe/scenes/scene34.cpp
+++ b/engines/fullpipe/scenes/scene34.cpp
@@ -392,7 +392,7 @@ int sceneHandler34(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case MSG_LIFT_GO:
@@ -426,7 +426,7 @@ int sceneHandler34(ExCommand *cmd) {
}
if (ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
diff --git a/engines/fullpipe/scenes/scene35.cpp b/engines/fullpipe/scenes/scene35.cpp
index f10786b821..a42849eeb5 100644
--- a/engines/fullpipe/scenes/scene35.cpp
+++ b/engines/fullpipe/scenes/scene35.cpp
@@ -199,7 +199,7 @@ int sceneHandler35(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case 29:
@@ -208,7 +208,7 @@ int sceneHandler35(ExCommand *cmd) {
if (ani)
if (ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
break;
}
diff --git a/engines/fullpipe/scenes/scene38.cpp b/engines/fullpipe/scenes/scene38.cpp
index 016dc83c1b..7fb0be8509 100644
--- a/engines/fullpipe/scenes/scene38.cpp
+++ b/engines/fullpipe/scenes/scene38.cpp
@@ -368,7 +368,7 @@ int sceneHandler38(ExCommand *cmd) {
break;
case 64:
- g_fp->lift_sub05(cmd);
+ g_fp->lift_hoverButton(cmd);
break;
case 29:
@@ -376,7 +376,7 @@ int sceneHandler38(ExCommand *cmd) {
StaticANIObject *ani = g_fp->_currentScene->getStaticANIObjectAtPos(g_fp->_sceneRect.left + cmd->_x, g_fp->_sceneRect.top + cmd->_y);
if (ani && ani->_id == ANI_LIFTBUTTON) {
- g_fp->lift_sub1(ani);
+ g_fp->lift_animateButton(ani);
cmd->_messageKind = 0;
}
diff --git a/engines/gob/detection/tables.h b/engines/gob/detection/tables.h
index 271f75af79..d042dfeede 100644
--- a/engines/gob/detection/tables.h
+++ b/engines/gob/detection/tables.h
@@ -55,6 +55,7 @@ static const PlainGameDescriptor gobGames[] = {
{"ajworld", "A.J.'s World of Discovery"},
{"gob3", "Goblins Quest 3"},
{"gob3cd", "Goblins Quest 3 CD"},
+ {"crousti", "Croustibat"},
{"lit1", "Lost in Time Part 1"},
{"lit2", "Lost in Time Part 2"},
{"lit", "Lost in Time"},
@@ -110,6 +111,7 @@ static const GOBGameDescription gameDescriptions[] = {
#include "gob/detection/tables_adi4.h" // The ADI / Addy 4 series
#include "gob/detection/tables_adibou.h" // The Adibou / Addy Junior series
#include "gob/detection/tables_ajworld.h" // A.J.'s World of Discovery / ADI Jr.
+ #include "gob/detection/tables_crousti.h" // Croustibat
{ AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0}
};
diff --git a/engines/avalanche/pingo.h b/engines/gob/detection/tables_crousti.h
index 6eecaf6453..da4cd461c1 100644
--- a/engines/avalanche/pingo.h
+++ b/engines/gob/detection/tables_crousti.h
@@ -20,37 +20,26 @@
*
*/
-/*
- * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
- * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
- */
-
-/* PINGO Full-screen sub-parts of the game. */
-
-#ifndef AVALANCHE_PINGO_H
-#define AVALANCHE_PINGO_H
-
-#include "common/str.h"
-
-namespace Avalanche {
-class AvalancheEngine;
-
-class Pingo {
-public:
- Pingo(AvalancheEngine *vm);
-
- void bossKey();
- void copy02();
- void copy03();
- void copyPage(byte frp, byte top);
- void winningPic();
-
-private:
- AvalancheEngine *_vm;
-
- void dPlot(int16 x, int16 y, Common::String z);
-};
-
-} // End of namespace Avalanche.
-
-#endif // AVALANCHE_PINGO_H
+/* Detection tables for Croustibat. */
+
+#ifndef GOB_DETECTION_TABLES_CROUSTI_H
+#define GOB_DETECTION_TABLES_CROUSTI_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "crousti",
+ "",
+ AD_ENTRY1s("intro.stk", "63fd795818fa72c32b903bbd99e18ea1", 851926),
+ PT_BRA,
+ kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeCrousti,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_CROUSTI_H
diff --git a/engines/gob/draw_fascin.cpp b/engines/gob/draw_fascin.cpp
index 12009d7ee5..c248cdf009 100644
--- a/engines/gob/draw_fascin.cpp
+++ b/engines/gob/draw_fascin.cpp
@@ -882,8 +882,6 @@ bool Draw_Fascination::overlapWin(int16 idWin1, int16 idWin2) {
void Draw_Fascination::activeWin(int16 id) {
bool found = false;
int16 t[10], t2[10];
- int nextId = -1;
- int oldId = -1;
SurfacePtr tempSrf;
SurfacePtr oldSrf[10];
@@ -906,6 +904,8 @@ void Draw_Fascination::activeWin(int16 id) {
}
if (found) {
+ int nextId = -1;
+ int oldId = -1;
for (int i = 9; i >= 0; i--) {
if (t[i] != -1) {
if (nextId != -1)
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index fcf98f0355..c50f4c42a0 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -457,6 +457,7 @@ Common::Error GobEngine::initGameParts() {
case kGameTypeWeen:
case kGameTypeGob2:
+ case kGameTypeCrousti:
_init = new Init_v2(this);
_video = new Video_v2(this);
_inter = new Inter_v2(this);
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index df73404596..e8da5fdcfc 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -55,6 +55,7 @@ class StaticTextWidget;
* - Bambou le sauveur de la jungle
* - Geisha
* - Once Upon A Time: Little Red Riding Hood
+ * - Croustibat
*/
namespace Gob {
@@ -134,7 +135,8 @@ enum GameType {
kGameTypeBabaYaga,
kGameTypeLittleRed,
kGameTypeOnceUponATime, // Need more inspection to see if Baba Yaga or Abracadabra
- kGameTypeAJWorld
+ kGameTypeAJWorld,
+ kGameTypeCrousti
};
enum Features {
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 2aa837e777..fabd31b66d 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -439,6 +439,7 @@ protected:
void o2_animPalInit(OpFuncParams &params);
void o2_addHotspot(OpFuncParams &params);
void o2_removeHotspot(OpFuncParams &params);
+ void o2_getTotTextItemPart(OpFuncParams &params);
void o2_goblinFunc(OpFuncParams &params);
void o2_stopSound(OpFuncParams &params);
void o2_loadSound(OpFuncParams &params);
@@ -540,7 +541,6 @@ protected:
virtual void setupOpcodesFunc();
virtual void setupOpcodesGob();
- void o3_getTotTextItemPart(OpFuncParams &params);
void o3_speakerOn(OpFuncParams &params);
void o3_speakerOff(OpFuncParams &params);
void o3_copySprite(OpFuncParams &params);
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 6b7a4f03bd..9346a6adb8 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -124,6 +124,7 @@ void Inter_v2::setupOpcodesFunc() {
OPCODEFUNC(0x18, o2_addHotspot);
OPCODEFUNC(0x19, o2_removeHotspot);
+ OPCODEFUNC(0x1A, o2_getTotTextItemPart);
OPCODEFUNC(0x25, o2_goblinFunc);
@@ -1195,6 +1196,188 @@ void Inter_v2::o2_removeHotspot(OpFuncParams &params) {
_vm->_game->_hotspots->remove((stateType2 << 12) + id);
}
+void Inter_v2::o2_getTotTextItemPart(OpFuncParams &params) {
+ byte *totData;
+ int16 totTextItem;
+ int16 part, curPart = 0;
+ int16 offX = 0, offY = 0;
+ int16 collId = 0, collCmd;
+ uint32 stringStartVar, stringVar;
+ bool end;
+
+ totTextItem = _vm->_game->_script->readInt16();
+ stringStartVar = _vm->_game->_script->readVarIndex();
+ part = _vm->_game->_script->readValExpr();
+
+ stringVar = stringStartVar;
+ if (part == -1) {
+ warning("o2_getTotTextItemPart, part == -1");
+ _vm->_draw->_hotspotText = GET_VARO_STR(stringVar);
+ }
+
+ WRITE_VARO_UINT8(stringVar, 0);
+
+ TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem);
+ if (!textItem)
+ return;
+
+ totData = textItem->getData();
+
+ // Skip background rectangles
+ while (((int16) READ_LE_UINT16(totData)) != -1)
+ totData += 9;
+ totData += 2;
+
+ while (*totData != 1) {
+ switch (*totData) {
+ case 2:
+ case 5:
+ totData++;
+ offX = READ_LE_UINT16(totData);
+ offY = READ_LE_UINT16(totData + 2);
+ totData += 4;
+ break;
+
+ case 3:
+ case 4:
+ totData += 2;
+ break;
+
+ case 6:
+ totData++;
+
+ collCmd = *totData++;
+ if (collCmd & 0x80) {
+ collId = READ_LE_UINT16(totData);
+ totData += 2;
+ }
+
+ // Skip collision coordinates
+ if (collCmd & 0x40)
+ totData += 8;
+
+ if ((collCmd & 0x8F) && ((-collId - 1) == part)) {
+ int n = 0;
+
+ while (1) {
+ if ((*totData < 1) || (*totData > 7)) {
+ if (*totData >= 32) {
+ WRITE_VARO_UINT8(stringVar++, *totData++);
+ n++;
+ } else
+ totData++;
+ continue;
+ }
+
+ if ((n != 0) || (*totData == 1) ||
+ (*totData == 6) || (*totData == 7)) {
+ WRITE_VARO_UINT8(stringVar, 0);
+ delete textItem;
+ return;
+ }
+
+ switch (*totData) {
+ case 2:
+ case 5:
+ totData += 5;
+ break;
+
+ case 3:
+ case 4:
+ totData += 2;
+ break;
+ }
+ }
+
+ }
+ break;
+
+ case 7:
+ case 8:
+ case 9:
+ totData++;
+ break;
+
+ case 10:
+ if (curPart == part) {
+ WRITE_VARO_UINT8(stringVar++, 0xFF);
+ WRITE_VARO_UINT16(stringVar, offX);
+ WRITE_VARO_UINT16(stringVar + 2, offY);
+ WRITE_VARO_UINT16(stringVar + 4,
+ totData - _vm->_game->_resources->getTexts());
+ WRITE_VARO_UINT8(stringVar + 6, 0);
+ delete textItem;
+ return;
+ }
+
+ end = false;
+ while (!end) {
+ switch (*totData) {
+ case 2:
+ case 5:
+ if (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)
+ end = true;
+ else
+ totData += 5;
+ break;
+
+ case 3:
+ totData += 2;
+ break;
+
+ case 10:
+ totData += totData[1] * 2 + 2;
+ break;
+
+ default:
+ if (*totData < 32)
+ end = true;
+ while (*totData >= 32)
+ totData++;
+ break;
+ }
+ }
+
+ if (part >= 0)
+ curPart++;
+ break;
+
+ default:
+ while (1) {
+
+ while (*totData >= 32)
+ WRITE_VARO_UINT8(stringVar++, *totData++);
+ WRITE_VARO_UINT8(stringVar, 0);
+
+ if (((*totData != 2) && (*totData != 5)) ||
+ (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) {
+
+ if (curPart == part) {
+ delete textItem;
+ return;
+ }
+
+ stringVar = stringStartVar;
+ WRITE_VARO_UINT8(stringVar, 0);
+
+ while (*totData >= 32)
+ totData++;
+
+ if (part >= 0)
+ curPart++;
+ break;
+
+ } else
+ totData += 5;
+
+ }
+ break;
+ }
+ }
+
+ delete textItem;
+}
+
void Inter_v2::o2_goblinFunc(OpFuncParams &params) {
OpGobParams gobParams;
int16 cmd;
diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp
index edf56012d9..d6d4c52476 100644
--- a/engines/gob/inter_v3.cpp
+++ b/engines/gob/inter_v3.cpp
@@ -50,7 +50,6 @@ void Inter_v3::setupOpcodesDraw() {
void Inter_v3::setupOpcodesFunc() {
Inter_v2::setupOpcodesFunc();
- OPCODEFUNC(0x1A, o3_getTotTextItemPart);
OPCODEFUNC(0x22, o3_speakerOn);
OPCODEFUNC(0x23, o3_speakerOff);
OPCODEFUNC(0x32, o3_copySprite);
@@ -66,188 +65,6 @@ void Inter_v3::setupOpcodesGob() {
OPCODEGOB(100, o3_wobble);
}
-void Inter_v3::o3_getTotTextItemPart(OpFuncParams &params) {
- byte *totData;
- int16 totTextItem;
- int16 part, curPart = 0;
- int16 offX = 0, offY = 0;
- int16 collId = 0, collCmd;
- uint32 stringStartVar, stringVar;
- bool end;
-
- totTextItem = _vm->_game->_script->readInt16();
- stringStartVar = _vm->_game->_script->readVarIndex();
- part = _vm->_game->_script->readValExpr();
-
- stringVar = stringStartVar;
- if (part == -1) {
- warning("o3_getTotTextItemPart, part == -1");
- _vm->_draw->_hotspotText = GET_VARO_STR(stringVar);
- }
-
- WRITE_VARO_UINT8(stringVar, 0);
-
- TextItem *textItem = _vm->_game->_resources->getTextItem(totTextItem);
- if (!textItem)
- return;
-
- totData = textItem->getData();
-
- // Skip background rectangles
- while (((int16) READ_LE_UINT16(totData)) != -1)
- totData += 9;
- totData += 2;
-
- while (*totData != 1) {
- switch (*totData) {
- case 2:
- case 5:
- totData++;
- offX = READ_LE_UINT16(totData);
- offY = READ_LE_UINT16(totData + 2);
- totData += 4;
- break;
-
- case 3:
- case 4:
- totData += 2;
- break;
-
- case 6:
- totData++;
-
- collCmd = *totData++;
- if (collCmd & 0x80) {
- collId = READ_LE_UINT16(totData);
- totData += 2;
- }
-
- // Skip collision coordinates
- if (collCmd & 0x40)
- totData += 8;
-
- if ((collCmd & 0x8F) && ((-collId - 1) == part)) {
- int n = 0;
-
- while (1) {
- if ((*totData < 1) || (*totData > 7)) {
- if (*totData >= 32) {
- WRITE_VARO_UINT8(stringVar++, *totData++);
- n++;
- } else
- totData++;
- continue;
- }
-
- if ((n != 0) || (*totData == 1) ||
- (*totData == 6) || (*totData == 7)) {
- WRITE_VARO_UINT8(stringVar, 0);
- delete textItem;
- return;
- }
-
- switch (*totData) {
- case 2:
- case 5:
- totData += 5;
- break;
-
- case 3:
- case 4:
- totData += 2;
- break;
- }
- }
-
- }
- break;
-
- case 7:
- case 8:
- case 9:
- totData++;
- break;
-
- case 10:
- if (curPart == part) {
- WRITE_VARO_UINT8(stringVar++, 0xFF);
- WRITE_VARO_UINT16(stringVar, offX);
- WRITE_VARO_UINT16(stringVar + 2, offY);
- WRITE_VARO_UINT16(stringVar + 4,
- totData - _vm->_game->_resources->getTexts());
- WRITE_VARO_UINT8(stringVar + 6, 0);
- delete textItem;
- return;
- }
-
- end = false;
- while (!end) {
- switch (*totData) {
- case 2:
- case 5:
- if (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)
- end = true;
- else
- totData += 5;
- break;
-
- case 3:
- totData += 2;
- break;
-
- case 10:
- totData += totData[1] * 2 + 2;
- break;
-
- default:
- if (*totData < 32)
- end = true;
- while (*totData >= 32)
- totData++;
- break;
- }
- }
-
- if (part >= 0)
- curPart++;
- break;
-
- default:
- while (1) {
-
- while (*totData >= 32)
- WRITE_VARO_UINT8(stringVar++, *totData++);
- WRITE_VARO_UINT8(stringVar, 0);
-
- if (((*totData != 2) && (*totData != 5)) ||
- (ABS(offY - READ_LE_UINT16(totData + 3)) > 1)) {
-
- if (curPart == part) {
- delete textItem;
- return;
- }
-
- stringVar = stringStartVar;
- WRITE_VARO_UINT8(stringVar, 0);
-
- while (*totData >= 32)
- totData++;
-
- if (part >= 0)
- curPart++;
- break;
-
- } else
- totData += 5;
-
- }
- break;
- }
- }
-
- delete textItem;
-}
-
void Inter_v3::o3_speakerOn(OpFuncParams &params) {
int16 frequency = _vm->_game->_script->readValExpr();
int32 length = -1;
diff --git a/engines/hopkins/anim.cpp b/engines/hopkins/anim.cpp
index 2ec9cec009..238f27616e 100644
--- a/engines/hopkins/anim.cpp
+++ b/engines/hopkins/anim.cpp
@@ -668,7 +668,6 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui
*/
void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
byte *screenP;
- int frameNumber;
Common::File f;
if (_vm->shouldQuit())
@@ -708,7 +707,7 @@ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, u
if (!_vm->_events->_escKeyFl) {
_vm->_events->_rateCounter = 0;
- frameNumber = 0;
+ int frameNumber = 0;
while (!_vm->shouldQuit()) {
_vm->_soundMan->playAnimSound(frameNumber++);
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index f9e3ecafcd..c42474de64 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -675,15 +675,12 @@ void ComputerManager::displayBricks() {
_breakoutSpeed = 1;
int16 *level = _breakoutLevel;
- int cellLeft;
- int cellTop;
- int cellType;
for (int levelIdx = 0; ; levelIdx += 6) {
- cellLeft = (int16)FROM_LE_16(level[levelIdx]);
+ int cellLeft = (int16)FROM_LE_16(level[levelIdx]);
if (cellLeft == -1)
break;
- cellTop = FROM_LE_16(level[levelIdx + 1]);
- cellType = FROM_LE_16(level[levelIdx + 4]);
+ int cellTop = FROM_LE_16(level[levelIdx + 1]);
+ int cellType = FROM_LE_16(level[levelIdx + 4]);
if (cellType <= 6)
++_breakoutBrickNbr;
@@ -833,7 +830,6 @@ int ComputerManager::displayHiscores() {
_vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
int yp;
- int xp;
// Loop for displaying the scores
for (int scoreIndex = 0; scoreIndex <= 5; scoreIndex++) {
yp = 19 * scoreIndex;
@@ -853,7 +849,7 @@ int ComputerManager::displayHiscores() {
int buttonIndex = 0;
do {
_vm->_events->refreshEvents();
- xp = _vm->_events->getMouseX();
+ int xp = _vm->_events->getMouseX();
yp = _vm->_events->getMouseY();
if (_vm->_events->getMouseButton() == 1 && ABS(xp - 79) <= 33 && ABS(yp - 396) <= 13)
diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp
index c617a5aacf..b81f51e607 100644
--- a/engines/hopkins/detection.cpp
+++ b/engines/hopkins/detection.cpp
@@ -29,6 +29,7 @@
#include "common/memstream.h"
#include "engines/advancedDetector.h"
#include "common/system.h"
+#include "common/translation.h"
#include "graphics/colormasks.h"
#include "graphics/surface.h"
@@ -69,6 +70,30 @@ static const PlainGameDescriptor hopkinsGames[] = {
#include "hopkins/detection_tables.h"
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_GORE_DEFAULT_OFF,
+ {
+ _s("Gore Mode"),
+ _s("Enable Gore Mode when available"),
+ "enable_gore",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_GORE_DEFAULT_ON,
+ {
+ _s("Gore Mode"),
+ _s("Enable Gore Mode when available"),
+ "enable_gore",
+ true
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
const static char *directoryGlobs[] = {
"voice",
"link",
@@ -77,7 +102,7 @@ const static char *directoryGlobs[] = {
class HopkinsMetaEngine : public AdvancedMetaEngine {
public:
- HopkinsMetaEngine() : AdvancedMetaEngine(Hopkins::gameDescriptions, sizeof(Hopkins::HopkinsGameDescription), hopkinsGames) {
+ HopkinsMetaEngine() : AdvancedMetaEngine(Hopkins::gameDescriptions, sizeof(Hopkins::HopkinsGameDescription), hopkinsGames, optionsList) {
_maxScanDepth = 3;
_directoryGlobs = directoryGlobs;
}
diff --git a/engines/hopkins/detection_tables.h b/engines/hopkins/detection_tables.h
index c3ff563f6f..c6db7ab253 100644
--- a/engines/hopkins/detection_tables.h
+++ b/engines/hopkins/detection_tables.h
@@ -22,6 +22,9 @@
namespace Hopkins {
+#define GAMEOPTION_GORE_DEFAULT_ON GUIO_GAMEOPTIONS1
+#define GAMEOPTION_GORE_DEFAULT_OFF GUIO_GAMEOPTIONS2
+
static const HopkinsGameDescription gameDescriptions[] = {
{
// Hopkins FBI Linux Demo UK 1.00 and 1.02
@@ -35,7 +38,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformLinux,
ADGF_DEMO,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -51,7 +54,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformOS2,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -66,7 +69,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformBeOS,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -81,7 +84,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::ES_ESP,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -96,7 +99,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_OFF)
},
},
{
@@ -111,7 +114,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::RU_RUS,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -126,7 +129,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformLinux,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -141,7 +144,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformLinux,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -156,11 +159,27 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::FR_FRA,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
+ // Hopkins FBI Win95 Polish, provided by Paput in bug #6511
+ {
+ "hopkins",
+ 0,
+ {
+ {"RES_VAN.RES", 0, "f2fec5172e4a7a9d35cb2a5f948ef6a9", 39400865},
+ AD_LISTEND
+ },
+ Common::PL_POL,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_GORE_DEFAULT_OFF)
+ },
+ },
+
+ {
// Hopkins FBI Win95 Demo, provided by Strangerke
// CHECKME: No voice! a second file is required though... Also, it has multi-language support
{
@@ -173,7 +192,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DEMO,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_ON)
},
},
{
@@ -188,7 +207,7 @@ static const HopkinsGameDescription gameDescriptions[] = {
Common::PL_POL,
Common::kPlatformWindows,
ADGF_DEMO,
- GUIO1(GUIO_NONE)
+ GUIO1(GAMEOPTION_GORE_DEFAULT_OFF)
},
},
{ AD_TABLE_END_MARKER }
diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp
index 2390ebbdf8..51d11afd91 100644
--- a/engines/hopkins/files.cpp
+++ b/engines/hopkins/files.cpp
@@ -25,6 +25,7 @@
#include "hopkins/hopkins.h"
#include "hopkins/globals.h"
+#include "common/config-manager.h"
#include "common/system.h"
#include "common/debug.h"
#include "common/file.h"
@@ -68,20 +69,11 @@ int FileManager::readStream(Common::ReadStream &stream, void *buf, size_t nbytes
}
/**
- * Initialize censorship based on blood.dat file
+ * The original censorship was based on blood.dat file.
+ * It's now using the config manager and a per-engine GUI option.
*/
void FileManager::initCensorship() {
- _vm->_globals->_censorshipFl = false;
-
- // If file doesn't exist, fallback to uncensored
- if (fileExists("BLOOD.DAT")) {
- char *data = (char *)loadFile("BLOOD.DAT");
-
- if ((data[6] == 'u' && data[7] == 'k') || (data[6] == 'U' && data[7] == 'K'))
- _vm->_globals->_censorshipFl = true;
-
- _vm->_globals->freeMemory((byte *)data);
- }
+ _vm->_globals->_censorshipFl = ConfMan.getBool("enable_gore");
}
/**
diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp
index a64e81fcc9..c47cf95152 100644
--- a/engines/hopkins/graphics.cpp
+++ b/engines/hopkins/graphics.cpp
@@ -439,9 +439,7 @@ void GraphicsManager::display8BitRect(const byte *surface, int xs, int ys, int w
}
void GraphicsManager::displayScaled8BitRect(const byte *surface, int xp, int yp, int width, int height, int destX, int destY) {
- int xCtr;
const byte *palette;
- int savedXCount;
byte *loopDestP;
const byte *loopSrcP;
int yCtr;
@@ -454,10 +452,10 @@ void GraphicsManager::displayScaled8BitRect(const byte *surface, int xp, int yp,
do {
yCtr = yCount;
- xCtr = xCount;
+ int xCtr = xCount;
loopSrcP = srcP;
loopDestP = destP;
- savedXCount = xCount;
+ int savedXCount = xCount;
palette = _palettePixels;
do {
diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp
index 0e86fa26a9..5d8661c4ae 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -232,7 +232,7 @@ bool HopkinsEngine::runWin95Demo() {
if (!_globals->_censorshipFl)
_animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200);
else
- _animMan->playAnim("BANQUE.ANM", "BANKUK.ANM", 200, 28, 200);
+ _animMan->playAnim("BANKUK.ANM", "BANQUE.ANM", 200, 28, 200);
_soundMan->_specialSoundNum = 0;
_soundMan->removeSample(1);
_soundMan->removeSample(2);
@@ -2860,7 +2860,6 @@ void HopkinsEngine::syncSoundSettings() {
}
bool HopkinsEngine::displayAdultDisclaimer() {
- int xp, yp;
int buttonIndex;
_graphicsMan->_minX = 0;
@@ -2880,8 +2879,8 @@ bool HopkinsEngine::displayAdultDisclaimer() {
_events->_mouseSpriteId = 0;
do {
- xp = _events->getMouseX();
- yp = _events->getMouseY();
+ int xp = _events->getMouseX();
+ int yp = _events->getMouseY();
buttonIndex = 0;
if (xp >= 37 && xp <= 169 && yp >= 406 && yp <= 445)
diff --git a/engines/hopkins/lines.cpp b/engines/hopkins/lines.cpp
index aa708fdfb2..e849f8635c 100644
--- a/engines/hopkins/lines.cpp
+++ b/engines/hopkins/lines.cpp
@@ -548,8 +548,6 @@ int LinesManager::avoidObstacleOnSegment(int lineIdx, int lineDataIdx, int route
bool LinesManager::MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, int routeIdx) {
debugC(5, kDebugPath, "MIRACLE(%d, %d, %d, %d, %d)", fromX, fromY, lineIdx, destLineIdx, routeIdx);
- int newLinesDataIdx = 0;
- int newLinesIdx = 0;
int lineIdxLeft = 0;
int lineDataIdxLeft = 0;
int lineIdxRight = 0;
@@ -700,6 +698,8 @@ bool LinesManager::MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, i
newDir = DIR_LEFT;
}
+ int newLinesDataIdx = 0;
+ int newLinesIdx = 0;
switch(newDir) {
case DIR_UP:
newLinesIdx = linesIdxUp;
@@ -1552,7 +1552,6 @@ void LinesManager::useRoute2(int idx, int curRouteIdx) {
int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int startLineIdx, int endLineIdx, int routeIdx) {
debugC(5, kDebugPath, "characterRoute(%d, %d, %d, %d, %d, %d, %d)", fromX, fromY, destX, destY, startLineIdx, endLineIdx, routeIdx);
int collDataIdxRoute2 = 0;
- bool colResult = false;
int curX = fromX;
int curY = fromY;
@@ -1603,7 +1602,6 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int
int collLineIdxRoute1 = -1;
int collLineIdxRoute2 = -1;
- int distX, distY;
int repeatFlag = 0;
int collDataIdxRoute0 = 0;
int collDataIdxRoute1 = 0;
@@ -1615,8 +1613,8 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int
useRoute0(idxRoute0, curRouteIdx);
return 1;
}
- distX = abs(curX - destX) + 1;
- distY = abs(curY - destY) + 1;
+ int distX = abs(curX - destX) + 1;
+ int distY = abs(curY - destY) + 1;
int maxDist;
if (distX > distY)
maxDist = distX;
@@ -1912,7 +1910,7 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int
posXRoute2 = _newPosX;
posYRoute2 = _newPosY;
- colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _lastLine);
+ bool colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _lastLine);
if (colResult && collLineIdxRoute2 <= _lastLine)
break;
}
@@ -2456,13 +2454,12 @@ bool LinesManager::PLAN_TEST(int paramX, int paramY, int superRouteIdx, int para
int LinesManager::testLine(int paramX, int paramY, int *testValue, int *foundLineIdx, int *foundDataIdx) {
debugC(5, kDebugPath, "testLine(%d, %d, testValue, foundLineIdx, foundDataIdx)", paramX, paramY);
int16 *lineData;
- int lineDataEndIdx;
int collLineIdx;
int collDataIdx;
for (int idx = _lastLine + 1; idx < _linesNumb + 1; idx++) {
lineData = _lineItem[idx]._lineData;
- lineDataEndIdx = _lineItem[idx]._lineDataEndIdx;
+ int lineDataEndIdx = _lineItem[idx]._lineDataEndIdx;
if (!lineData)
continue;
diff --git a/engines/hopkins/objects.cpp b/engines/hopkins/objects.cpp
index 347a6aabe8..2c780dd428 100644
--- a/engines/hopkins/objects.cpp
+++ b/engines/hopkins/objects.cpp
@@ -376,7 +376,6 @@ void ObjectsManager::addObject(int objIndex) {
void ObjectsManager::displaySprite() {
int clipX;
int clipY;
- bool loopCondFl;
uint16 arr[50];
// Handle copying any background areas that text are going to be drawn on
@@ -441,6 +440,7 @@ void ObjectsManager::displaySprite() {
for (int i = 1; i <= 48; i++)
arr[i] = i;
+ bool loopCondFl;
do {
loopCondFl = false;
for (int sortIdx = 1; sortIdx < _sortedDisplayCount; sortIdx++) {
@@ -3613,12 +3613,10 @@ void ObjectsManager::showSpecialActionAnimation(const byte *spriteData, const Co
realSpeed = speed / 3;
int spriteIndex = 0;
- bool completeTokenFl;
- char nextChar;
for (int idx = 0; ; idx++) {
- completeTokenFl = false;
- nextChar = animString[idx];
+ bool completeTokenFl = false;
+ char nextChar = animString[idx];
if (nextChar == ',') {
spriteIndex = atoi(tmpStr.c_str());
tmpStr = "";
diff --git a/engines/hopkins/sound.cpp b/engines/hopkins/sound.cpp
index 92c5f51462..704ebe3349 100644
--- a/engines/hopkins/sound.cpp
+++ b/engines/hopkins/sound.cpp
@@ -200,14 +200,6 @@ SoundManager::SoundManager(HopkinsEngine *vm) {
_currentSoundIndex = 0;
_oldSoundNumber = 0;
_modPlayingFl = false;
-
- for (int i = 0; i < VOICE_COUNT; ++i)
- Common::fill((byte *)&_voice[i], (byte *)&_voice[i] + sizeof(VoiceItem), 0);
- for (int i = 0; i < SWAV_COUNT; ++i)
- Common::fill((byte *)&_sWav[i], (byte *)&_sWav[i] + sizeof(SwavItem), 0);
- for (int i = 0; i < SOUND_COUNT; ++i)
- Common::fill((byte *)&_sound[i], (byte *)&_sound[i] + sizeof(SoundItem), 0);
- Common::fill((byte *)&_music, (byte *)&_music + sizeof(MusicItem), 0);
}
SoundManager::~SoundManager() {
diff --git a/engines/hopkins/sound.h b/engines/hopkins/sound.h
index f1d047ae8b..6ebb6fdb02 100644
--- a/engines/hopkins/sound.h
+++ b/engines/hopkins/sound.h
@@ -33,12 +33,16 @@ namespace Hopkins {
class VoiceItem {
public:
+ VoiceItem() : _status(false), _wavIndex(0) {}
+
bool _status;
int _wavIndex;
};
class SwavItem {
public:
+ SwavItem() : _active(false), _audioStream(NULL), _freeSampleFl(false) {}
+
bool _active;
Audio::RewindableAudioStream *_audioStream;
Audio::SoundHandle _soundHandle;
@@ -47,11 +51,15 @@ public:
class MusicItem {
public:
+ MusicItem() : _active(false) {}
+
bool _active;
};
class SoundItem {
public:
+ SoundItem() : _active(false) {}
+
bool _active;
};
diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp
index c80ea15554..b6faf8b6fe 100644
--- a/engines/hopkins/talk.cpp
+++ b/engines/hopkins/talk.cpp
@@ -613,7 +613,6 @@ void TalkManager::displayBobDialogAnim(int idx) {
_vm->_objectsMan->_bob[idx]._flipFl = false;
_vm->_objectsMan->_bob[idx]._animData = _vm->_animMan->_animBqe[idx]._data;
_vm->_objectsMan->_bob[idx]._bobMode = 10;
- bqeData = _characterSprite;
_vm->_objectsMan->_bob[idx]._spriteData = _characterSprite;
_vm->_objectsMan->_bob[idx]._bobModeChange = newMode;
_vm->_objectsMan->_bob[idx]._modeChangeCtr = -1;
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index ede4ab2279..ee41fe33f2 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -184,13 +184,12 @@ SaveStateList HugoMetaEngine::listSaves(const char *target) const {
SaveStateList saveList;
char slot[3];
- int slotNum = 0;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
slot[0] = filename->c_str()[filename->size() - 6];
slot[1] = filename->c_str()[filename->size() - 5];
slot[2] = '\0';
// Obtain the last 2 digits of the filename (without extension), since they correspond to the save slot
- slotNum = atoi(slot);
+ int slotNum = atoi(slot);
if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
if (file) {
diff --git a/engines/hugo/dialogs.cpp b/engines/hugo/dialogs.cpp
index 23e04dc479..333c14778d 100644
--- a/engines/hugo/dialogs.cpp
+++ b/engines/hugo/dialogs.cpp
@@ -107,7 +107,6 @@ void TopMenu::reflowLayout() {
x += kButtonWidth + kButtonPad;
_inventButton->resize(x * scale, y * scale, kButtonWidth * scale, kButtonHeight * scale);
- x += kButtonWidth + kButtonPad;
// Set the graphics to the 'on' buttons, except for the variable ones
_whatButton->setGfx(_arrayBmp[4 * kMenuWhat + scale - 1]);
diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp
index 4ef3db3e2b..4b874756a0 100644
--- a/engines/hugo/mouse.cpp
+++ b/engines/hugo/mouse.cpp
@@ -160,7 +160,6 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in
return;
int16 inventObjId = _vm->_inventory->getInventoryObjId();
- bool foundFl = false; // TRUE if route found to object
// Check if this was over iconbar
if ((_vm->_inventory->getInventoryState() == kInventoryActive) && (cy < kInvDy + kDibOffY)) { // Clicked over iconbar object
if (inventObjId == -1)
@@ -172,12 +171,14 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in
} else { // Clicked over viewport object
Object *obj = &_vm->_object->_objects[objId];
int16 x, y;
- switch (obj->_viewx) { // Where to walk to
- case -1: // Walk to object position
+ switch (obj->_viewx) { // Where to walk to
+ case -1: { // Walk to object position
+ bool foundFl = false;
if (_vm->_object->findObjectSpace(obj, &x, &y))
- foundFl = _vm->_route->startRoute(kRouteGet, objId, x, y);
+ foundFl = _vm->_route->startRoute(kRouteGet, objId, x, y); // TRUE if route found to object
if (!foundFl) // Can't get there, try to use from here
_vm->_object->useObject(objId);
+ }
break;
case 0: // Immediate use
_vm->_object->useObject(objId); // Pick up or use object
diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp
index 44f46d2d79..315214c5a4 100644
--- a/engines/hugo/object.cpp
+++ b/engines/hugo/object.cpp
@@ -134,19 +134,19 @@ void ObjectHandler::restoreSeq(Object *obj) {
void ObjectHandler::useObject(int16 objId) {
debugC(1, kDebugObject, "useObject(%d)", objId);
- const char *verb; // Background verb to use directly
int16 inventObjId = _vm->_inventory->getInventoryObjId();
- Object *obj = &_objects[objId]; // Ptr to object
+ Object *obj = &_objects[objId]; // Ptr to object
if (inventObjId == -1) {
+ const char *verb; // Background verb to use directly
// Get or use objid directly
if ((obj->_genericCmd & TAKE) || obj->_objValue) // Get collectible item
sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_take, 0), _vm->_text->getNoun(obj->_nounIndex, 0));
- else if (obj->_cmdIndex != 0) // Use non-collectible item if able
+ else if (obj->_cmdIndex != 0) // Use non-collectible item if able
sprintf(_vm->_line, "%s %s", _vm->_text->getVerb(_vm->_parser->getCmdDefaultVerbIdx(obj->_cmdIndex), 0), _vm->_text->getNoun(obj->_nounIndex, 0));
else if ((verb = _vm->_parser->useBG(_vm->_text->getNoun(obj->_nounIndex, 0))) != 0)
sprintf(_vm->_line, "%s %s", verb, _vm->_text->getNoun(obj->_nounIndex, 0));
else
- return; // Can't use object directly
+ return; // Can't use object directly
} else {
// Use status.objid on objid
// Default to first cmd verb
@@ -540,10 +540,8 @@ void ObjectHandler::setCarriedScreen(int screenNum) {
* Load _numObj from Hugo.dat
*/
void ObjectHandler::loadNumObj(Common::ReadStream &in) {
- int numElem;
-
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
- numElem = in.readUint16BE();
+ int numElem = in.readUint16BE();
if (varnt == _vm->_gameVariant)
_numObj = numElem;
}
diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp
index dc3c41de9c..c4ffa6c7ca 100644
--- a/engines/hugo/route.cpp
+++ b/engines/hugo/route.cpp
@@ -384,9 +384,9 @@ bool Route::findRoute(const int16 cx, const int16 cy) {
_segment[_segmentNumb]._x2 = herox2;
_segmentNumb++;
- Common::Point *routeNode; // Ptr to route node
// Look in segments[] for straight lines from destination to hero
for (i = 0, _routeListIndex = 0; i < _segmentNumb - 1; i++) {
+ Common::Point *routeNode; // Ptr to route node
if ((routeNode = newNode()) == 0) // New node for new segment
return false; // Too many nodes
routeNode->y = _segment[i]._y;
@@ -438,7 +438,7 @@ bool Route::findRoute(const int16 cx, const int16 cy) {
void Route::processRoute() {
debugC(1, kDebugRoute, "processRoute");
- static bool turnedFl = false; // Used to get extra cylce for turning
+ static bool turnedFl = false; // Used to get extra cycle for turning
if (_routeIndex < 0)
return;
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index 17ffa9d391..e8359bfdfc 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -254,9 +254,8 @@ void Scheduler::waitForRefresh() {
void Scheduler::loadAlNewscrIndex(Common::ReadStream &in) {
debugC(6, kDebugSchedule, "loadAlNewscrIndex(&in)");
- int numElem;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
- numElem = in.readUint16BE();
+ int numElem = in.readUint16BE();
if (varnt == _vm->_gameVariant)
_alNewscrIndex = numElem;
}
@@ -568,9 +567,9 @@ void Scheduler::loadActListArr(Common::ReadStream &in) {
Act tmpAct;
- int numElem, numSubElem;
+ int numSubElem;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
- numElem = in.readUint16BE();
+ int numElem = in.readUint16BE();
if (varnt == _vm->_gameVariant) {
_actListArrSize = numElem;
_actListArr = (Act **)malloc(sizeof(Act *) * _actListArrSize);
@@ -1214,8 +1213,6 @@ Event *Scheduler::doAction(Event *curEvent) {
Act *action = curEvent->_action;
Object *obj1;
int dx, dy;
- Event *wrkEvent; // Save ev_p->nextEvent for return
-
switch (action->_a0._actType) {
case ANULL: // Big NOP from DEL_EVENTS
break;
@@ -1444,7 +1441,7 @@ Event *Scheduler::doAction(Event *curEvent) {
if (action->_a0._actType == NEW_SCREEN) { // New_screen() deletes entire list
return nullptr; // nextEvent = nullptr since list now empty
} else {
- wrkEvent = curEvent->_nextEvent;
+ Event *wrkEvent = curEvent->_nextEvent;
delQueue(curEvent); // Return event to free list
return wrkEvent; // Return next event ptr
}
@@ -1601,10 +1598,9 @@ void Scheduler_v2d::promptAction(Act *action) {
debug(1, "doAction(act3), expecting answer %s", _vm->_file->fetchString(action->_a3._responsePtr[0]));
bool found = false;
- const char *tmpStr; // General purpose string ptr
for (int dx = 0; !found && (action->_a3._responsePtr[dx] != -1); dx++) {
- tmpStr = _vm->_file->fetchString(action->_a3._responsePtr[dx]);
+ const char *tmpStr = _vm->_file->fetchString(action->_a3._responsePtr[dx]);
if (response.contains(tmpStr))
found = true;
}
diff --git a/engines/hugo/text.cpp b/engines/hugo/text.cpp
index 538a0341e2..5e7505744c 100644
--- a/engines/hugo/text.cpp
+++ b/engines/hugo/text.cpp
@@ -91,16 +91,14 @@ char **TextHandler::getVerbArray(int idx1) const {
}
char **TextHandler::loadTextsVariante(Common::ReadStream &in, uint16 *arraySize) {
- int numTexts;
- int entryLen;
int len;
char **res = nullptr;
char *pos = nullptr;
char *posBck = nullptr;
for (int varnt = 0; varnt < _vm->_numVariant; varnt++) {
- numTexts = in.readUint16BE();
- entryLen = in.readUint16BE();
+ int numTexts = in.readUint16BE();
+ int entryLen = in.readUint16BE();
pos = (char *)malloc(entryLen);
if (varnt == _vm->_gameVariant) {
if (arraySize)
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 9fcce4eb55..776a3e50b0 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -1651,7 +1651,7 @@ void SeqPlayer_HOF::displayHoFTalkieScrollText(uint8 *data, const ScreenDim *d,
textData[1].text += strlen((char *)textData[1].text);
textData[1].text[0] = textData[1].unk1;
cnt--;
- memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData));
+ memmove(&textData[1], &textData[2], cnt * sizeof(ScrollTextData));
}
if (palCycle) {
diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp
index f7a4e23006..95eb4f3080 100644
--- a/engines/kyra/timer_eob.cpp
+++ b/engines/kyra/timer_eob.cpp
@@ -347,7 +347,7 @@ void EoBCoreEngine::timerUpdateFoodStatus(int timerNum) {
}
void EoBCoreEngine::timerUpdateMonsterIdleAnim(int timerNum) {
- for (int i = 0; i < 18; i++) {
+ for (int i = 0; i < 30; i++) {
EoBMonsterInPlay *m = &_monsters[i];
if (m->mode == 7 || m->mode == 10 || (m->flags & 0x20) || (rollDice(1, 2, 0) != 1))
continue;
diff --git a/engines/mortevielle/actions.cpp b/engines/mortevielle/actions.cpp
index c5d55066ba..e13220d248 100644
--- a/engines/mortevielle/actions.cpp
+++ b/engines/mortevielle/actions.cpp
@@ -481,13 +481,24 @@ void MortevielleEngine::fctLook() {
}
return;
}
+
int cx = _coreVar._currPlace;
- if (_coreVar._currPlace == CHAPEL)
+ switch (_coreVar._currPlace) {
+ case CHAPEL:
cx = 17;
- if ((_coreVar._currPlace > MANOR_FRONT) && (_coreVar._currPlace < DOOR))
+ break;
+ case MANOR_BACK:
+ case INSIDE_WELL:
+ case WELL:
cx -= 4;
- if (_coreVar._currPlace == ROOM26)
+ break;
+ case ROOM26:
cx = 21;
+ break;
+ default:
+ break;
+ }
+
_crep = _tabdon[kArega + (cx * 7) + _num - 1];
if ((_coreVar._currPlace == ATTIC) && (_num == 8))
_crep = 126;
diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp
index 09a4227cc0..1ab2af7008 100644
--- a/engines/mortevielle/dialogs.cpp
+++ b/engines/mortevielle/dialogs.cpp
@@ -292,7 +292,7 @@ bool DialogManager::showKnowledgeCheck() {
Common::String choiceArray[15];
- int currChoice, prevChoice;
+ int currChoice;
int correctCount = 0;
for (int indx = 0; indx < 10; ++indx) {
@@ -317,7 +317,7 @@ bool DialogManager::showKnowledgeCheck() {
int optionPosY = 35;
int maxLength = 0;
- prevChoice = 1;
+ int prevChoice = 1;
for (int j = firstOption; j <= lastOption; ++j, ++prevChoice) {
tmpStr = _vm->getString(j);
if ((int) tmpStr.size() > maxLength)
diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp
index 2077a4cdc5..d71934ad1a 100644
--- a/engines/mortevielle/mouse.cpp
+++ b/engines/mortevielle/mouse.cpp
@@ -97,15 +97,13 @@ void MouseHandler::getMousePosition(int &x, int &y, bool &click) {
* @remarks Originally called 'mov_mouse'
*/
void MouseHandler::moveMouse(bool &funct, char &key) {
- bool p_key;
- char in1, in2;
int cx, cy;
bool click;
// Set defaults and check pending events
funct = false;
key = '\377';
- p_key = _vm->keyPressed();
+ bool p_key = _vm->keyPressed();
// If mouse button clicked, return it
if (_vm->getMouseClick())
@@ -116,7 +114,7 @@ void MouseHandler::moveMouse(bool &funct, char &key) {
if (_vm->shouldQuit())
return;
- in1 = _vm->getChar();
+ char in1 = _vm->getChar();
getMousePosition(cx, cy, click);
switch (toupper(in1)) {
case '4':
@@ -160,7 +158,7 @@ void MouseHandler::moveMouse(bool &funct, char &key) {
p_key = _vm->keyPressed();
if (p_key) {
- in2 = _vm->getChar();
+ char in2 = _vm->getChar();
if ((in2 >= ';') && (in2 <= 'D')) {
funct = true;
diff --git a/engines/mortevielle/sound.cpp b/engines/mortevielle/sound.cpp
index db1f7578f1..1270eeb63e 100644
--- a/engines/mortevielle/sound.cpp
+++ b/engines/mortevielle/sound.cpp
@@ -91,13 +91,12 @@ int SoundManager::decodeMusic(const byte *PSrc, byte *PDest, int size) {
static const int tab[16] = { -96, -72, -48, -32, -20, -12, -8, -4, 0, 4, 8, 12, 20, 32, 48, 72 };
uint seed = 128;
- int v;
int decompSize = 0;
int skipSize = 0;
for (int idx1 = 0; idx1 < size; ++idx1) {
byte srcByte = *PSrc++;
- v = tab[srcByte >> 4];
+ int v = tab[srcByte >> 4];
seed += v;
*PDest++ = seed & 0xff;
diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp
index 29c9be2e0c..d24585a677 100644
--- a/engines/mortevielle/utils.cpp
+++ b/engines/mortevielle/utils.cpp
@@ -258,7 +258,6 @@ void MortevielleEngine::handleAction() {
clearVerbBar();
- bool handledOpcodeFl = false;
_controlMenu = 0;
if (!_keyPressedEsc) {
_menu->drawMenu();
@@ -319,6 +318,7 @@ void MortevielleEngine::handleAction() {
_menuOpcode = _currMenu;
if ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF))
_menuOpcode = _currAction;
+ bool handledOpcodeFl = false;
if (!_anyone) {
if ((_heroSearching) || (_obpart)) {
if (_mouse->_pos.y < 12)
diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
index 99efe10272..75f652ad56 100644
--- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
@@ -2691,16 +2691,18 @@ void FullTSA::receiveNotification(Notification *notification, const Notification
}
break;
case kTSA37DownloadToOpMemReview:
- switch (GameState.getTSAState()) {
- case kPlayerOnWayToNorad:
- g_opticalChip->playOpMemMovie(kPoseidonSpotID);
- break;
- case kPlayerOnWayToMars:
- g_opticalChip->playOpMemMovie(kAriesSpotID);
- break;
- case kPlayerOnWayToWSC:
- g_opticalChip->playOpMemMovie(kMercurySpotID);
- break;
+ if (_vm->itemInBiochips(kOpticalBiochip)) {
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ g_opticalChip->playOpMemMovie(kPoseidonSpotID);
+ break;
+ case kPlayerOnWayToMars:
+ g_opticalChip->playOpMemMovie(kAriesSpotID);
+ break;
+ case kPlayerOnWayToWSC:
+ g_opticalChip->playOpMemMovie(kMercurySpotID);
+ break;
+ }
}
if (GameState.allTimeZonesFinished()) {
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
index 0d11f5d904..0326c7f2ee 100644
--- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
@@ -372,16 +372,18 @@ void TinyTSA::receiveNotification(Notification *notification, const Notification
}
break;
case kTinyTSA37DownloadToOpMemReview:
- switch (GameState.getTSAState()) {
- case kPlayerOnWayToNorad:
- g_opticalChip->playOpMemMovie(kPoseidonSpotID);
- break;
- case kPlayerOnWayToMars:
- g_opticalChip->playOpMemMovie(kAriesSpotID);
- break;
- case kPlayerOnWayToWSC:
- g_opticalChip->playOpMemMovie(kMercurySpotID);
- break;
+ if (_vm->itemInBiochips(kOpticalBiochip)) {
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ g_opticalChip->playOpMemMovie(kPoseidonSpotID);
+ break;
+ case kPlayerOnWayToMars:
+ g_opticalChip->playOpMemMovie(kAriesSpotID);
+ break;
+ case kPlayerOnWayToWSC:
+ g_opticalChip->playOpMemMovie(kMercurySpotID);
+ break;
+ }
}
requestExtraSequence(kTinyTSA37OpMemReviewToMainMenu, kExtraCompletedFlag, kFilterNoInput);
diff --git a/engines/queen/detection.cpp b/engines/queen/detection.cpp
new file mode 100644
index 0000000000..57b314c088
--- /dev/null
+++ b/engines/queen/detection.cpp
@@ -0,0 +1,512 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+
+#include "common/config-manager.h"
+#include "common/file.h"
+#include "common/gui_options.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/translation.h"
+
+#include "queen/queen.h"
+#include "queen/resource.h"
+
+namespace Queen {
+
+struct QueenGameDescription {
+ ADGameDescription desc;
+};
+
+} // End of namespace Queen
+
+static const PlainGameDescriptor queenGames[] = {
+ {"queen", "Flight of the Amazon Queen"},
+ {0, 0}
+};
+
+#define GAMEOPTION_ALT_INTRO GUIO_GAMEOPTIONS1
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_ALT_INTRO,
+ {
+ _s("Alternative intro"),
+ _s("Use an alternative game intro (CD version only)"),
+ "alt_intro",
+ false
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
+namespace Queen {
+
+static const QueenGameDescription gameDescriptions[] = {
+ // Amiga Demo - English
+ {
+ {
+ "queen",
+ "Demo",
+ AD_ENTRY1s("queen.1", "f7a1a37ac93bf763b1569231237cb4d8", 563335),
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
+ // Amiga Interview Demo - English
+ {
+ {
+ "queen",
+ "Interview",
+ AD_ENTRY1s("queen.1", "f5d42a18d8f5689480413871410663d7", 597032),
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
+ // DOS Demo - English
+ {
+ {
+ "queen",
+ "Demo",
+ AD_ENTRY1s("queen.1", "f39334d8133840aa3bcbd733c12937cf", 3732177),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
+ // DOS Interview Demo - English
+ {
+ {
+ "queen",
+ "Interview",
+ AD_ENTRY1s("queen.1", "30b3291f37665bf24d9482b183cb2f67", 1915913),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
+ // PCGAMES DOS Demo - English
+ {
+ {
+ "queen",
+ "Demo",
+ AD_ENTRY1s("queen.1", "f39334d8133840aa3bcbd733c12937cf", 3724538),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
+#if 0
+ // Amiga Floppy - English
+ {
+ {
+ "queen",
+ "Floppy",
+ AD_ENTRY1s("queen.1", NULL, 351775), // TODO: Fill in correct MD5
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+#endif
+
+ // DOS Floppy - English
+ {
+ {
+ "queen",
+ "Floppy",
+ AD_ENTRY1s("queen.1", "f5e827645d3c887be3bdf4729d847756", 22677657),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+
+ // DOS CD - English
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190787021),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+#if 0
+ // DOS Floppy - French
+ {
+ {
+ "queen",
+ "Floppy",
+ AD_ENTRY1s("queen.1", NULL, 22157304), // TODO: Fill in correct MD5
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+#endif
+
+#if 0
+ // DOS CD - French
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", NULL, 186689095), // TODO: Fill in correct MD5
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+#endif
+
+#if 0
+ // DOS Floppy - German
+ {
+ {
+ "queen",
+ "Floppy",
+ AD_ENTRY1s("queen.1", NULL, 22240013), // TODO: Fill in correct MD5
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+#endif
+
+#if 0
+ // DOS CD - German
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", NULL, 217648975), // TODO: Fill in correct MD5
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+#endif
+
+#if 0
+ // DOS CD - Hebrew
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", NULL, 190705558), // TODO: Fill in correct MD5
+ Common::HE_ISR,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+#endif
+
+#if 0
+ // DOS Floppy - Italian
+ {
+ {
+ "queen",
+ "Floppy",
+ AD_ENTRY1s("queen.1", NULL, 22461366), // TODO: Fill in correct MD5
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSPEECH)
+ },
+ },
+#endif
+
+ // DOS CD - Italian
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", "b6302bccf70463de3d5faf0f0628f742", 190795582),
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+#if 0
+ // DOS CD - Spanish
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", NULL, 190730602), // TODO: Fill in correct MD5
+ Common::ES_ESP,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+#endif
+
+ // DOS CD - English (Compressed Freeware Release v1.0)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", "a0749bb8b72e537ead1a63a3dde1443d", 54108887),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // DOS CD - English (Compressed Freeware Release v1.1)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", "21fd690b372f8a6289f6f33bc986276c", 51222412),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // DOS CD - French (Compressed Freeware Release v1.0)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", "67e3020f8a35e1df7b1c753b5aaa71e1", 97382620),
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // DOS CD - German (Compressed Freeware Release v1.0)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", "28f78dbec7e20f603a10c2f8ea889a5c", 108738717),
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // DOS CD - Hebrew (Compressed Freeware Release v1.0)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", "4d52d8780613ef27a2b779caecb20a21", 99391805),
+ Common::HE_ISR,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // DOS CD - Italian (Compressed Freeware Release v1.0)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", "2f72b715ed753cf905a37cdcc7ea611e", 98327801),
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // TODO: Freeware Release for Spanish DOS CD is missing.
+#if 0
+ // DOS CD - Spanish (Compressed Freeware Release v1.0)
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1c", NULL, ?),
+ Common::ES_ESP,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+#endif
+
+ { AD_TABLE_END_MARKER }
+};
+
+} // End of namespace Queen
+
+class QueenMetaEngine : public AdvancedMetaEngine {
+public:
+ QueenMetaEngine() : AdvancedMetaEngine(Queen::gameDescriptions, sizeof(Queen::QueenGameDescription), queenGames, optionsList) {
+ _singleid = "queen";
+ }
+
+ virtual const char *getName() const {
+ return "Queen";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const { return 99; }
+ virtual void removeSaveState(const char *target, int slot) const;
+
+ const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+};
+
+bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave);
+}
+
+const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ static ADGameDescription desc;
+
+ // Iterate over all files in the given directory
+ for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ if (file->isDirectory()) {
+ continue;
+ }
+ if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) {
+ Common::File dataFile;
+ if (!dataFile.open(*file)) {
+ continue;
+ }
+ Queen::DetectedGameVersion version;
+ if (Queen::Resource::detectVersion(&version, &dataFile)) {
+ desc.gameid = "queen";
+ desc.language = version.language;
+ desc.platform = version.platform;
+ desc.flags = ADGF_NO_FLAGS;
+ desc.guioptions = GUIO0();
+ if (version.features & Queen::GF_DEMO) {
+ desc.extra = "Demo";
+ desc.flags = ADGF_DEMO;
+ desc.guioptions = GUIO_NOSPEECH;
+ } else if (version.features & Queen::GF_INTERVIEW) {
+ desc.extra = "Interview";
+ desc.flags = ADGF_DEMO;
+ desc.guioptions = GUIO_NOSPEECH;
+ } else if (version.features & Queen::GF_FLOPPY) {
+ desc.extra = "Floppy";
+ desc.guioptions = GUIO_NOSPEECH;
+ } else if (version.features & Queen::GF_TALKIE) {
+ desc.extra = "Talkie";
+ desc.guioptions = GAMEOPTION_ALT_INTRO;
+ }
+ return (const ADGameDescription *)&desc;
+ }
+ }
+ }
+ return 0;
+}
+
+SaveStateList QueenMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ char saveDesc[32];
+ Common::String pattern("queen.s??");
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ // Obtain the last 2 digits of the filename, since they correspond to the save slot
+ int slotNum = atoi(file->c_str() + file->size() - 2);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+ Common::InSaveFile *in = saveFileMan->openForLoading(*file);
+ if (in) {
+ for (int i = 0; i < 4; i++)
+ in->readUint32BE();
+ in->read(saveDesc, 32);
+ saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+void QueenMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String filename = Common::String::format("queen.s%02d", slot);
+
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
+bool QueenMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Queen::QueenGameDescription *gd = (const Queen::QueenGameDescription *)desc;
+
+ if (gd)
+ *engine = new Queen::QueenEngine(syst); //FIXME , gd);
+
+ return (gd != 0);
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(QUEEN)
+ REGISTER_PLUGIN_DYNAMIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine);
+#endif
diff --git a/engines/queen/module.mk b/engines/queen/module.mk
index 5e0602cae7..8ba49a301d 100644
--- a/engines/queen/module.mk
+++ b/engines/queen/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
credits.o \
cutaway.o \
debug.o \
+ detection.o \
display.o \
graphics.o \
grid.o \
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index 08fc594560..8d4db75cc1 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -23,14 +23,12 @@
#include "base/plugins.h"
#include "common/config-manager.h"
+#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
-#include "common/gui_options.h"
#include "common/savefile.h"
#include "common/system.h"
-#include "common/events.h"
#include "common/textconsole.h"
-#include "common/translation.h"
#include "engines/util.h"
@@ -49,177 +47,6 @@
#include "queen/talk.h"
#include "queen/walk.h"
-#include "engines/metaengine.h"
-
-static const PlainGameDescriptor queenGameDescriptor = {
- "queen", "Flight of the Amazon Queen"
-};
-
-static const ExtraGuiOption queenExtraGuiOption = {
- _s("Alternative intro"),
- _s("Use an alternative game intro (CD version only)"),
- "alt_intro",
- false
-};
-
-class QueenMetaEngine : public MetaEngine {
-public:
- virtual const char *getName() const;
- virtual const char *getOriginalCopyright() const;
-
- virtual bool hasFeature(MetaEngineFeature f) const;
- virtual GameList getSupportedGames() const;
- virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
- virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const Common::FSList &fslist) const;
- virtual SaveStateList listSaves(const char *target) const;
- virtual int getMaximumSaveSlot() const;
- virtual void removeSaveState(const char *target, int slot) const;
-
- virtual Common::Error createInstance(OSystem *syst, Engine **engine) const;
-};
-
-const char *QueenMetaEngine::getName() const {
- return "Queen";
-}
-
-const char *QueenMetaEngine::getOriginalCopyright() const {
- return "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis";
-}
-
-bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const {
- return
- (f == kSupportsListSaves) ||
- (f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave);
-}
-
-bool Queen::QueenEngine::hasFeature(EngineFeature f) const {
- return
- (f == kSupportsRTL) ||
- (f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime) ||
- (f == kSupportsSubtitleOptions);
-}
-
-GameList QueenMetaEngine::getSupportedGames() const {
- GameList games;
- games.push_back(queenGameDescriptor);
- return games;
-}
-
-int QueenMetaEngine::getMaximumSaveSlot() const { return 99; }
-
-const ExtraGuiOptions QueenMetaEngine::getExtraGuiOptions(const Common::String &target) const {
- Common::String guiOptions;
- ExtraGuiOptions options;
-
- if (target.empty()) {
- options.push_back(queenExtraGuiOption);
- return options;
- }
-
- if (ConfMan.hasKey("guioptions", target)) {
- guiOptions = ConfMan.get("guioptions", target);
- guiOptions = parseGameGUIOptions(guiOptions);
- }
-
- if (!guiOptions.contains(GUIO_NOSPEECH))
- options.push_back(queenExtraGuiOption);
- return options;
-}
-
-GameDescriptor QueenMetaEngine::findGame(const char *gameid) const {
- if (0 == scumm_stricmp(gameid, queenGameDescriptor.gameid)) {
- return queenGameDescriptor;
- }
- return GameDescriptor();
-}
-
-GameList QueenMetaEngine::detectGames(const Common::FSList &fslist) const {
- GameList detectedGames;
-
- // Iterate over all files in the given directory
- for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory()) {
- continue;
- }
- if (file->getName().equalsIgnoreCase("queen.1") || file->getName().equalsIgnoreCase("queen.1c")) {
- Common::File dataFile;
- if (!dataFile.open(*file)) {
- continue;
- }
- Queen::DetectedGameVersion version;
- if (Queen::Resource::detectVersion(&version, &dataFile)) {
- GameDescriptor dg(queenGameDescriptor.gameid, queenGameDescriptor.description, version.language, version.platform);
- if (version.features & Queen::GF_DEMO) {
- dg.updateDesc("Demo");
- dg.setGUIOptions(GUIO_NOSPEECH);
- } else if (version.features & Queen::GF_INTERVIEW) {
- dg.updateDesc("Interview");
- dg.setGUIOptions(GUIO_NOSPEECH);
- } else if (version.features & Queen::GF_FLOPPY) {
- dg.updateDesc("Floppy");
- dg.setGUIOptions(GUIO_NOSPEECH);
- } else if (version.features & Queen::GF_TALKIE) {
- dg.updateDesc("Talkie");
- }
- detectedGames.push_back(dg);
- break;
- }
- }
- }
- return detectedGames;
-}
-
-SaveStateList QueenMetaEngine::listSaves(const char *target) const {
- Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
- Common::StringArray filenames;
- char saveDesc[32];
- Common::String pattern("queen.s??");
-
- filenames = saveFileMan->listSavefiles(pattern);
- sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
-
- SaveStateList saveList;
- for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
- // Obtain the last 2 digits of the filename, since they correspond to the save slot
- int slotNum = atoi(file->c_str() + file->size() - 2);
-
- if (slotNum >= 0 && slotNum <= 99) {
- Common::InSaveFile *in = saveFileMan->openForLoading(*file);
- if (in) {
- for (int i = 0; i < 4; i++)
- in->readUint32BE();
- in->read(saveDesc, 32);
- saveList.push_back(SaveStateDescriptor(slotNum, saveDesc));
- delete in;
- }
- }
- }
-
- return saveList;
-}
-
-void QueenMetaEngine::removeSaveState(const char *target, int slot) const {
- Common::String filename = target;
- filename += Common::String::format(".s%02d", slot);
-
- g_system->getSavefileManager()->removeSavefile(filename);
-}
-
-Common::Error QueenMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
- assert(engine);
- *engine = new Queen::QueenEngine(syst);
- return Common::kNoError;
-}
-
-#if PLUGIN_ENABLED_DYNAMIC(QUEEN)
- REGISTER_PLUGIN_DYNAMIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine);
-#else
- REGISTER_PLUGIN_STATIC(QUEEN, PLUGIN_TYPE_ENGINE, QueenMetaEngine);
-#endif
-
namespace Queen {
QueenEngine::QueenEngine(OSystem *syst)
@@ -488,6 +315,14 @@ GUI::Debugger *QueenEngine::getDebugger() {
return _debugger;
}
+bool Queen::QueenEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime) ||
+ (f == kSupportsSubtitleOptions);
+}
+
Common::Error QueenEngine::run() {
initGraphics(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT, false);
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 0f0c8dcd66..d26a519233 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -252,7 +252,7 @@ Common::String SciEngine::getSciLanguageString(const Common::String &str, kLangu
}
}
- if (seeker)
+ if (*seeker)
return Common::String(str.c_str(), seeker - str.c_str());
else
return str;
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 52155cd09a..3b3f3edb38 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -2264,15 +2264,6 @@ void ResourceManager::detectSciVersion() {
s_sciVersion = SCI_VERSION_1_1;
return;
}
- // FIXME: this is really difficult, lsl1 spanish has map/vol sci1late
- // and the only current detection difference is movecounttype which
- // is increment here, but ignore for all the regular sci1late games
- // the problem is, we dont have access to that detection till later
- // so maybe (part of?) that detection should get moved in here
- if (g_sci && (g_sci->getGameId() == GID_LSL1) && (g_sci->getLanguage() == Common::ES_ESP)) {
- s_sciVersion = SCI_VERSION_1_MIDDLE;
- return;
- }
s_sciVersion = SCI_VERSION_1_LATE;
return;
case kResVersionSci11:
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 7b1456b05c..72cf57af8a 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -184,10 +184,10 @@ void ToonEngine::parseInput() {
Common::Event event;
while (_event->pollEvent(event)) {
- bool hasModifier = event.kbd.hasFlags(Common::KBD_ALT|Common::KBD_CTRL|Common::KBD_SHIFT);
+ const bool hasModifier = (event.kbd.flags & Common::KBD_NON_STICKY) != 0;
switch (event.type) {
case Common::EVENT_KEYDOWN:
- if ((event.kbd.ascii == 27 || event.kbd.ascii == 32) && !hasModifier) {
+ if ((event.kbd.keycode == Common::KEYCODE_ESCAPE || event.kbd.keycode == Common::KEYCODE_SPACE) && !hasModifier) {
_audioManager->stopCurrentVoice();
}
if (event.kbd.keycode == Common::KEYCODE_F5 && !hasModifier) {
@@ -198,21 +198,21 @@ void ToonEngine::parseInput() {
if (canLoadGameStateCurrently())
loadGame(-1);
}
- if (event.kbd.ascii == 't' && !hasModifier) {
+ if (event.kbd.keycode == Common::KEYCODE_t && !hasModifier) {
_showConversationText = !_showConversationText;
}
- if (event.kbd.ascii == 'm' && !hasModifier) {
+ if (event.kbd.keycode == Common::KEYCODE_m && !hasModifier) {
_audioManager->muteMusic(!_audioManager->isMusicMuted());
}
- if (event.kbd.ascii == 'd' && !hasModifier) {
+ if (event.kbd.keycode == Common::KEYCODE_d && !hasModifier) {
_audioManager->muteVoice(!_audioManager->isVoiceMuted());
}
- if (event.kbd.ascii == 's' && !hasModifier) {
+ if (event.kbd.keycode == Common::KEYCODE_s && !hasModifier) {
_audioManager->muteSfx(!_audioManager->isSfxMuted());
}
if (event.kbd.flags & Common::KBD_ALT) {
- int slotNum = event.kbd.ascii - '0';
+ int slotNum = event.kbd.keycode - (event.kbd.keycode >= Common::KEYCODE_KP0 ? Common::KEYCODE_KP0 : Common::KEYCODE_0);
if (slotNum >= 0 && slotNum <= 9 && canSaveGameStateCurrently()) {
if (saveGame(slotNum, "")) {
// ok
@@ -229,7 +229,7 @@ void ToonEngine::parseInput() {
}
if (event.kbd.flags & Common::KBD_CTRL) {
- int slotNum = event.kbd.ascii - '0';
+ int slotNum = event.kbd.keycode - (event.kbd.keycode >= Common::KEYCODE_KP0 ? Common::KEYCODE_KP0 : Common::KEYCODE_0);
if (slotNum >= 0 && slotNum <= 9 && canLoadGameStateCurrently()) {
if (loadGame(slotNum)) {
// ok
diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp
index 85ca519f05..045b594aed 100644
--- a/engines/touche/menu.cpp
+++ b/engines/touche/menu.cpp
@@ -569,29 +569,29 @@ int ToucheEngine::displayQuitDialog() {
quitLoop = true;
switch (_language) {
case Common::FR_FRA:
- if (event.kbd.ascii == 'o' || event.kbd.ascii == 'O') {
+ if (event.kbd.keycode == Common::KEYCODE_o) {
ret = 1;
}
break;
case Common::DE_DEU:
- if (event.kbd.ascii == 'j' || event.kbd.ascii == 'J') {
+ if (event.kbd.keycode == Common::KEYCODE_j) {
ret = 1;
}
break;
case Common::ES_ESP:
- if (event.kbd.ascii == 's' || event.kbd.ascii == 'S') {
+ if (event.kbd.keycode == Common::KEYCODE_s) {
ret = 1;
}
break;
case Common::PL_POL:
- if (event.kbd.ascii == 's' || event.kbd.ascii == 'S' || event.kbd.ascii == 't' || event.kbd.ascii == 'T') {
+ if (event.kbd.keycode == Common::KEYCODE_s || event.kbd.keycode == Common::KEYCODE_t) {
ret = 1;
}
break;
default:
// According to cyx, the Italian version uses the same
// keys as the English one.
- if (event.kbd.ascii == 'y' || event.kbd.ascii == 'Y') {
+ if (event.kbd.keycode == Common::KEYCODE_y) {
ret = 1;
}
break;
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index b3e3ca5b50..eb7010a824 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -416,13 +416,13 @@ void ToucheEngine::processEvents(bool handleKeyEvents) {
this->getDebugger()->onFrame();
}
} else {
- if (event.kbd.ascii == 't') {
+ if (event.kbd.keycode == Common::KEYCODE_t) {
++_talkTextMode;
if (_talkTextMode == kTalkModeCount) {
_talkTextMode = 0;
}
displayTextMode(-(92 + _talkTextMode));
- } else if (event.kbd.ascii == ' ') {
+ } else if (event.kbd.keycode == Common::KEYCODE_SPACE) {
updateKeyCharTalk(2);
}
}
diff --git a/engines/tsage/blue_force/blueforce_scenes3.cpp b/engines/tsage/blue_force/blueforce_scenes3.cpp
index feaf789392..28005845d3 100644
--- a/engines/tsage/blue_force/blueforce_scenes3.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes3.cpp
@@ -4438,7 +4438,7 @@ void Scene360::postInit(SceneObjectList *OwnerList) {
BF_GLOBALS._player._moveDiff.y = 4;
BF_GLOBALS._player.enableControl();
- if ((BF_GLOBALS._sceneManager._previousScene == 355) || (BF_GLOBALS._sceneManager._previousScene != 370)) {
+ if (BF_GLOBALS._sceneManager._previousScene != 370) {
BF_GLOBALS._player.setPosition(Common::Point(253, 135));
BF_GLOBALS._player.setStrip(2);
diff --git a/engines/tsage/blue_force/blueforce_scenes5.cpp b/engines/tsage/blue_force/blueforce_scenes5.cpp
index 101a39c4b7..d3ea36a078 100644
--- a/engines/tsage/blue_force/blueforce_scenes5.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes5.cpp
@@ -1623,7 +1623,7 @@ void Scene570::PasswordEntry::process(Event &event) {
checkPassword();
remove();
- } else if ((key >= 32) || (key <= 126)) {
+ } else if ((key >= 32) && (key <= 126)) {
// Valid character pressed
if (_entryBuffer.size() < 10)
_entryBuffer += (char)key;
diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp
index 405a436f55..a3dd3688be 100644
--- a/engines/tsage/blue_force/blueforce_scenes9.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes9.cpp
@@ -516,7 +516,7 @@ void Scene900::postInit(SceneObjectList *OwnerList) {
_door.setPosition(Common::Point(847, 45));
_door._flag = 1;
- if ((BF_GLOBALS._sceneManager._previousScene == 880) || (BF_GLOBALS._sceneManager._previousScene != 910)) {
+ if (BF_GLOBALS._sceneManager._previousScene != 910) {
BF_GLOBALS._walkRegions.disableRegion(26);
BF_GLOBALS._player.disableControl();
if (BF_GLOBALS._bookmark == bFinishedWGreen) {
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index 16fe45044b..ba14830add 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -1593,12 +1593,12 @@ bool SceneItem::startAction(CursorType action, Event &event) {
}
void SceneItem::doAction(int action) {
- const char *msg = NULL;
-
if (g_vm->getGameID() == GType_Ringworld2) {
Event dummyEvent;
((Ringworld2::SceneExt *)GLOBALS._sceneManager._scene)->display((CursorType)action, dummyEvent);
} else {
+ const char *msg = NULL;
+
switch ((int)action) {
case CURSOR_LOOK:
msg = LOOK_SCENE_HOTSPOT;
@@ -2909,7 +2909,6 @@ void BackgroundSceneObject::copySceneToBackground() {
void SceneObjectList::draw() {
Common::Array<SceneObject *> objList;
int paneNum = 0;
- int xAmount = 0, yAmount = 0;
if (_objList.size() == 0) {
// Alternate draw mode
@@ -2936,6 +2935,7 @@ void SceneObjectList::draw() {
g_globals->_scrollFollower->_position.x - g_globals->_sceneManager._scene->_sceneBounds.left,
g_globals->_scrollFollower->_position.y - g_globals->_sceneManager._scene->_sceneBounds.top);
int loadCount = 0;
+ int xAmount = 0, yAmount = 0;
if (objPos.x >= scrollerRect.right) {
xAmount = 8;
diff --git a/engines/tsage/core.h b/engines/tsage/core.h
index c285fba669..6e50cc8d2e 100644
--- a/engines/tsage/core.h
+++ b/engines/tsage/core.h
@@ -465,7 +465,7 @@ enum AnimateMode {ANIM_MODE_NONE = 0, ANIM_MODE_1 = 1, ANIM_MODE_2 = 2, ANIM_MOD
};
// Actor effect enumeration used in Return to Ringworld 2
-enum Effect { EFFECT_NONE = 0, EFFECT_SHADED = 1, EFFECT_3 = 3,
+enum Effect { EFFECT_NONE = 0, EFFECT_SHADED = 1, EFFECT_SMOKE = 3,
EFFECT_SHADOW_MAP = 5, EFFECT_SHADED2 = 6 };
class SceneObject;
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index 97857aca34..eb7adbe53a 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -1483,7 +1483,6 @@ int GfxFont::getStringFit(const char *&s, int maxWidth) {
const char *nextWord = NULL;
const char *sStart = s;
int numChars = 1;
- int strWidth = 1;
char nextChar;
for (;;) {
@@ -1497,7 +1496,7 @@ int GfxFont::getStringFit(const char *&s, int maxWidth) {
nextWord = s;
}
- strWidth = getStringWidth(sStart, numChars);
+ int strWidth = getStringWidth(sStart, numChars);
if (strWidth > maxWidth) {
if (nextWord) {
s = nextWord;
diff --git a/engines/tsage/ringworld/ringworld_dialogs.cpp b/engines/tsage/ringworld/ringworld_dialogs.cpp
index 4728e66cd9..d512806903 100644
--- a/engines/tsage/ringworld/ringworld_dialogs.cpp
+++ b/engines/tsage/ringworld/ringworld_dialogs.cpp
@@ -385,7 +385,6 @@ void InventoryDialog::execute() {
if ((RING_INVENTORY._selectedItem) && RING_INVENTORY._selectedItem->inInventory())
RING_INVENTORY._selectedItem->setCursor();
- GfxElement *hiliteObj;
bool lookFlag = false;
_gfxManager.activate();
@@ -399,7 +398,7 @@ void InventoryDialog::execute() {
if (g_vm->shouldQuit())
break;
- hiliteObj = NULL;
+ GfxElement *hiliteObj = nullptr;
if ((event.eventType == EVENT_BUTTON_DOWN) && !_bounds.contains(event.mousePos))
break;
diff --git a/engines/tsage/ringworld/ringworld_scenes10.cpp b/engines/tsage/ringworld/ringworld_scenes10.cpp
index eac181e350..116dca10e9 100644
--- a/engines/tsage/ringworld/ringworld_scenes10.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes10.cpp
@@ -1217,7 +1217,7 @@ void Scene9500::postInit(SceneObjectList *OwnerList) {
g_globals->_events.setCursor(CURSOR_WALK);
g_globals->_player.disableControl();
- if ((g_globals->_sceneManager._previousScene == 9200) || (g_globals->_sceneManager._previousScene != 9850)) {
+ if (g_globals->_sceneManager._previousScene != 9850) {
_sceneMode = 0;
if (RING_INVENTORY._helmet._sceneNumber != 1) {
setAction(&_sequenceManager, this, 9501, &g_globals->_player, &_candle, NULL);
diff --git a/engines/tsage/ringworld/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp
index e834e659b5..5f33652458 100644
--- a/engines/tsage/ringworld/ringworld_scenes3.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes3.cpp
@@ -4946,8 +4946,6 @@ void Scene2310::synchronize(Serializer &s) {
}
void Scene2310::process(Event &event) {
- int frameNum = 0;
-
if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN)) {
int idx = 0;
while (idx < 5) {
@@ -4961,7 +4959,7 @@ void Scene2310::process(Event &event) {
if (_wireIndex == 5) {
// No wire is currently active, so start moving designated wire
_wireIndex = idx;
- frameNum = idx + 2;
+ int frameNum = idx + 2;
if (event.mousePos.y > 105)
idx = findObject(idx);
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
index 3e35831138..24504f2f5a 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
@@ -316,7 +316,7 @@ void CharacterDialog::show() {
}
// Reset the current cursor
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
// Change to whichever scene the newly selected character is in
R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex]);
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index 39e398023d..c67e5c18c2 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -561,14 +561,14 @@ void SceneExt::saveCharacter(int characterIndex) {
void SceneExt::scalePalette(int RFactor, int GFactor, int BFactor) {
byte *tmpPal = R2_GLOBALS._scenePalette._palette;
byte newR, newG, newB;
- int tmp, varC, varD = 0;
+ int tmp, varD = 0;
for (int i = 0; i < 256; i++) {
newR = (RFactor * tmpPal[(3 * i)]) / 100;
newG = (GFactor * tmpPal[(3 * i) + 1]) / 100;
newB = (BFactor * tmpPal[(3 * i) + 2]) / 100;
- varC = 769;
+ int varC = 769;
for (int j = 255; j >= 0; j--) {
tmp = abs(tmpPal[(3 * j)] - newR);
if (tmp >= varC)
@@ -625,6 +625,11 @@ void SceneHandlerExt::process(Event &event) {
SceneHandler::process(event);
}
+void SceneHandlerExt::dispatch() {
+ R2_GLOBALS._playStream.dispatch();
+ SceneHandler::dispatch();
+}
+
void SceneHandlerExt::postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) {
// Set up the shading maps used for showing the player in shadows
setupPaletteMaps();
@@ -2329,7 +2334,7 @@ void ScannerDialog::Button::reset() {
case 1800:
if (R2_GLOBALS._rimLocation < 1201)
scanner._obj4.setup(4, 3, 3);
- else if (R2_GLOBALS._rimLocation < 1201)
+ else if (R2_GLOBALS._rimLocation > 1201)
scanner._obj4.setup(4, 3, 4);
else
scanner._obj4.setup(4, 3, 5);
diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h
index c9695c921d..101b0f53cd 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.h
+++ b/engines/tsage/ringworld2/ringworld2_logic.h
@@ -114,6 +114,7 @@ public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void process(Event &event);
virtual void postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad);
+ virtual void dispatch();
void setupPaletteMaps();
};
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index 2fbce0646c..fc7e34bc16 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -1678,7 +1678,7 @@ void Scene180::signal() {
case 24:
case 26:
case 46:
- setSceneDelay((R2_GLOBALS._speechSubtitles & 1) ? 1 : 18);
+ setSceneDelay((R2_GLOBALS._speechSubtitles & SPEECH_TEXT) ? 1 : 18);
break;
case 13:
@@ -3486,7 +3486,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS.clearFlag(60);
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
_sceneMode = 16;
- _stripManager.start(404, this);
+ _stripManager.start3(404, this, R2_GLOBALS._stripManager_lookupList);
} else {
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
@@ -4151,11 +4151,22 @@ void Scene325::signal() {
--v;
if (_priorConsoleAction == 5)
v += 8;
+
if (R2_GLOBALS.getFlag(51) && (v == 2))
R2_GLOBALS.setFlag(57);
if (R2_GLOBALS.getFlag(44) && !R2_GLOBALS.getFlag(51)) {
if (v != 13) {
+ if (_priorConsoleAction == 6) {
+ // Fix for original game bug.
+ // The passive short scan geographical and astronomical sentences
+ // are inverted in the original game.
+ if (v == 6)
+ v = 8;
+ else if (v == 8)
+ v = 6;
+ }
+
setMessage(328, v);
} else {
_scannerLocation = 864;
@@ -4302,12 +4313,12 @@ void Scene325::signal() {
if (_soundCount)
--_soundCount;
- if (!_soundCount || (R2_GLOBALS._speechSubtitles == 2)) {
+ if (!_soundCount || !(R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
_soundIndex = 0;
R2_GLOBALS._playStream.stop();
} else {
_sceneMode = 15;
- R2_GLOBALS._playStream.play(_soundQueue[_soundIndex], this);
+ R2_GLOBALS._playStream.play(_soundQueue[_soundIndex++], this);
}
break;
default:
@@ -4513,6 +4524,7 @@ void Scene325::consoleAction(int id) {
case 14:
if (R2_GLOBALS.getFlag(55)) {
consoleAction(4);
+ // Workaround for original game bug.
// Empty message crashing the game. It should be a warning message forbidding to switch to active scan
// SceneItem::display2(329, 17);
} else {
@@ -4688,7 +4700,7 @@ void Scene325::setMessage(int resNum, int lineNum) {
R2_GLOBALS._sceneObjects->draw();
- if ((_soundCount != 0) && (R2_GLOBALS._speechSubtitles != 2)) {
+ if ((_soundCount != 0) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
_sceneMode = 15;
R2_GLOBALS._playStream.play(_soundQueue[_soundIndex++], this);
}
@@ -5753,24 +5765,47 @@ bool Scene600::Smoke::startAction(CursorType action, Event &event) {
return false;
}
-GfxSurface Scene600::Smoke::getFrame() {
- GfxSurface frame = SceneActor::getFrame();
+void Scene600::Smoke::draw() {
+ // Effect should always be active on smoke, but since the original had this
+ // check, include it here too
+ if (_effect == EFFECT_NONE) {
+ SceneActor::draw();
+ return;
+ }
- if (_effect) {
- // Translate the frame using the scene's pixel map
- byte *pixelMap = static_cast<Scene600 *>(R2_GLOBALS._sceneManager._scene)->_pixelMap;
- Graphics::Surface surface = frame.lockSurface();
- byte *srcP = (byte *)surface.getPixels();
+ // Determine the area of the screen to be updated
+ Rect destRect = _bounds;
+ destRect.translate(-g_globals->_sceneManager._scene->_sceneBounds.left,
+ -g_globals->_sceneManager._scene->_sceneBounds.top);
- while (srcP < ((byte *)surface.getBasePtr(0, surface.h))) {
- *srcP = pixelMap[*srcP];
- srcP++;
- }
+ // Get the smoke frame, screen reference, and pixel palette translation map
+ GfxSurface frame = getFrame();
+ Graphics::Surface s = frame.lockSurface();
+ Graphics::Surface screen = g_globals->gfxManager().getSurface().lockSurface();
+ byte *pixelMap = static_cast<Scene600 *>(R2_GLOBALS._sceneManager._scene)->_pixelMap;
- frame.unlockSurface();
+ // Loop through every pixel of the frame. Any pixel of the frame that's not a
+ // tranparency, get the same pixel from the screen background, and shade it using
+ // the scene's pixel translation map
+ for (int yp = 0; yp < s.h; ++yp) {
+ byte *frameSrcP = (byte *)s.getBasePtr(0, yp);
+ byte *screenP = (byte *)screen.getBasePtr(destRect.left, destRect.top + yp);
+
+ for (int xp = 0; xp < s.w; ++xp, ++frameSrcP, ++screenP) {
+ if (*frameSrcP != frame._transColor) {
+ *frameSrcP = pixelMap[*screenP];
+ }
+ }
}
- return frame;
+ // Finished updating the frame
+ frame.unlockSurface();
+ g_globals->gfxManager().getSurface().unlockSurface();
+
+ // Draw the processed frame
+ Region *priorityRegion = g_globals->_sceneManager._scene->_priorities.find(_priority);
+ g_globals->gfxManager().copyFrom(frame, destRect, priorityRegion);
+
}
bool Scene600::Doorway::startAction(CursorType action, Event &event) {
@@ -5846,7 +5881,7 @@ bool Scene600::Laser::startAction(CursorType action, Event &event) {
scene->_smoke.postInit();
scene->_smoke.setup(601, 3, 1);
- scene->_smoke._effect = EFFECT_3;
+ scene->_smoke._effect = EFFECT_SMOKE;
scene->_smoke._moveDiff = Common::Point(1, 1);
scene->_smoke._moveRate = 2;
scene->_smoke._numFrames = 3;
@@ -6027,7 +6062,7 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
_smoke._numFrames = 3;
_smoke.animate(ANIM_MODE_2, NULL);
_smoke.fixPriority(130);
- _smoke._effect = EFFECT_3;
+ _smoke._effect = EFFECT_SMOKE;
_smoke.setDetails(600, 24, 25, 26, 1, (SceneItem *) NULL);
_smoke.signal();
}
@@ -6098,7 +6133,7 @@ void Scene600::signal() {
R2_INVENTORY.setObjectScene(R2_AEROSOL, 600);
R2_GLOBALS.setFlag(5);
- _smoke._effect = EFFECT_3;
+ _smoke._effect = EFFECT_SMOKE;
_smoke.signal();
break;
case 606:
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.h b/engines/tsage/ringworld2/ringworld2_scenes0.h
index 216039a348..ba93dda652 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.h
@@ -661,7 +661,7 @@ class Scene600 : public SceneExt {
public:
virtual void signal();
virtual bool startAction(CursorType action, Event &event);
- virtual GfxSurface getFrame();
+ virtual void draw();
};
class Doorway : public SceneActor {
public:
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
index 075420a1c9..486c88e65d 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
@@ -3913,8 +3913,6 @@ void Scene1337::Action10::signal() {
void Scene1337::Action11::signal() {
Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
- bool noAction = true;
-
switch (_actionIndex++) {
case 0: {
scene->_actionCard2->_card.postInit();
@@ -3944,6 +3942,8 @@ void Scene1337::Action11::signal() {
scene->_aSound1.play(57);
bool found = false;
+ bool noAction = true;
+
int i = -1;
switch (scene->_actionIdx2) {
@@ -5411,10 +5411,10 @@ void Scene1337::showOptionsDialog() {
}
void Scene1337::handleClick(int arg1, Common::Point pt) {
- bool found = false;
int curReg = R2_GLOBALS._sceneRegions.indexOf(g_globals->_events._mousePos);
if (arg1 == 3) {
+ bool found = false;
int i;
for (i = 0; i <= 7; i++) {
if ( _gameBoardSide[2]._outpostStation[i].isIn(pt)
@@ -7439,7 +7439,7 @@ void Scene1550::DishControlsWindow::setup2(int visage, int stripFrameNum, int fr
if (scene->_dish._frame == 1)
_lever.setup(1559, 2, 1);
else
- _lever.setup(1559, 2, 2);
+ _lever.setup(1559, 2, 5);
_lever.setPosition(Common::Point(156, 103));
_lever.fixPriority(251);
_lever.setDetails(1550, 69, -1, -1, 2, (SceneItem *) NULL);
@@ -7773,7 +7773,7 @@ void Scene1550::signal() {
_dishControlsWindow.remove();
_sceneMode = 20;
setAction(&_sequenceManager1, this, 1566, &_dish, &_dishTowerShadow, NULL);
- R2_GLOBALS.setFlag(21);
+ R2_GLOBALS.setFlag(19);
break;
case 24:
_dishControlsWindow.remove();
@@ -8699,7 +8699,7 @@ void Scene1550::enterArea() {
warning("missing for loop, to be implemented");
warning("gfx_draw_slice");
}
- warning("Missing sub2957D()");
+ warning("gfx_flip_screen()");
warning("gfx_set_pane_p()");
#endif
R2_GLOBALS._sceneManager._fadeMode = FADEMODE_IMMEDIATE;
@@ -11190,7 +11190,7 @@ void Scene1800::SouthExit::changeScene() {
if (R2_GLOBALS._player._characterIndex == R2_QUINN)
scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_companion, NULL);
else
- scene->setAction(&scene->_sequenceManager, scene, 1802, &R2_GLOBALS._player, &scene->_companion, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 1803, &R2_GLOBALS._player, &scene->_companion, NULL);
}
}
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
index f928f3635c..ad9dbf5a98 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
@@ -4872,10 +4872,10 @@ void Scene2900::Map::drawBlock(const byte *data, int xp, int yp,
void Scene2900::Map::moveArea(Rect &r, int xAmt, int yAmt) {
Rect tempRect = r;
tempRect.translate(xAmt, yAmt);
- int xpSrc, xpDest, width;
- int ypSrc, ypDest, height;
if (tempRect.intersects(r)) {
+ int xpSrc, xpDest, width;
+ int ypSrc, ypDest, height;
if (xAmt >= 0) {
xpSrc = tempRect.left;
width = tempRect.width() - xAmt;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
index e55ae8ff70..36d7bf845b 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
@@ -1275,7 +1275,7 @@ void Scene3250::signal() {
}
void Scene3250::dispatch() {
- if ((R2_GLOBALS._player._visage == 3250) && (R2_GLOBALS._player._strip == 3) && (R2_GLOBALS._player._effect == 0)) {
+ if ((R2_GLOBALS._player._visage == 3250) && (R2_GLOBALS._player._strip == 3) && (R2_GLOBALS._player._effect == EFFECT_NONE)) {
R2_GLOBALS._player._effect = EFFECT_SHADED2;
R2_GLOBALS._player._shade = 6;
}
@@ -2221,24 +2221,24 @@ void Scene3375::signal() {
}
void Scene3375::dispatch() {
- if ((R2_GLOBALS._player._position.y >= 168) && (R2_GLOBALS._player._effect == 1))
+ if ((R2_GLOBALS._player._position.y >= 168) && (R2_GLOBALS._player._effect == EFFECT_SHADED))
R2_GLOBALS._player._effect = EFFECT_SHADED2;
- else if ((R2_GLOBALS._player._position.y < 168) && (R2_GLOBALS._player._effect == 6))
+ else if ((R2_GLOBALS._player._position.y < 168) && (R2_GLOBALS._player._effect == EFFECT_SHADED2))
R2_GLOBALS._player._effect = EFFECT_SHADED;
- if ((_companion1._position.y >= 168) && (_companion1._effect == 1))
+ if ((_companion1._position.y >= 168) && (_companion1._effect == EFFECT_SHADED))
_companion1._effect = EFFECT_SHADED2;
- else if ((_companion1._position.y < 168) && (_companion1._effect == 6))
+ else if ((_companion1._position.y < 168) && (_companion1._effect == EFFECT_SHADED2))
_companion1._effect = EFFECT_SHADED;
- if ((_companion2._position.y >= 168) && (_companion2._effect == 1))
+ if ((_companion2._position.y >= 168) && (_companion2._effect == EFFECT_SHADED))
_companion2._effect = EFFECT_SHADED2;
- else if ((_companion2._position.y < 168) && (_companion2._effect == 6))
+ else if ((_companion2._position.y < 168) && (_companion2._effect == EFFECT_SHADED2))
_companion2._effect = EFFECT_SHADED;
- if ((_webbster._position.y >= 168) && (_webbster._effect == 1))
+ if ((_webbster._position.y >= 168) && (_webbster._effect == EFFECT_SHADED))
_webbster._effect = EFFECT_SHADED2;
- else if ((_webbster._position.y < 168) && (_webbster._effect == 6))
+ else if ((_webbster._position.y < 168) && (_webbster._effect == EFFECT_SHADED2))
_webbster._effect = EFFECT_SHADED;
Scene::dispatch();
@@ -3896,7 +3896,6 @@ void Scene3500::dispatch() {
int16 mazePosY = 0;
int deltaX = 0;
int deltaY = 0;
- int tmpCellId = 0;
int cellId = 0;
if ((_mazeChangeAmount == 0) && !_postFixupFl) {
@@ -3912,7 +3911,7 @@ void Scene3500::dispatch() {
mazePosY = _mazeUI.cellFromY(_mazePosition.y + 46) - 46;
deltaX = abs(mazePosX - newMazeX);
deltaY = abs(mazePosY - newMazeY);
- tmpCellId = 0;
+ int tmpCellId = 0;
switch (_mazeDirection) {
case MAZEDIR_NORTH:
@@ -3956,7 +3955,7 @@ void Scene3500::dispatch() {
if ( (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (newMazeY <= mazePosY) && (_mazePosition.y>= mazePosY))
|| (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= deltaY) && (_mazeChangeAmount > 3) && (_action1._turningFl != 0)) ) {
newMazeY = mazePosY;
- if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId == 15))
+ if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId != 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_speed = 0;
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index 04e83efbe5..d443cd3a88 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -3682,7 +3682,8 @@ void TuckerEngine::setActionForInventoryObject() {
_actionRequiresTwoObjects = false;
return;
}
- if ((_partNum == 3 && (_actionObj1Num == 6 || _actionObj1Num == 3 || _actionObj1Num == 17)) ||
+ // Items with unary usage i.e. "Use X", rather than "Use X on Y"
+ if ((_partNum == 3 && (_actionObj1Num == 6 || _actionObj1Num == 3 || _actionObj1Num == 17 || _actionObj1Num == 33)) ||
(_partNum == 2 && _actionObj1Num == 19) ||
(_partNum == 3 && (_actionObj1Num == 42 && _selectedObjectNum == 18)) ) {
_actionVerbLocked = 0;
diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp
index ab7ab51f30..df944ba8eb 100644
--- a/engines/wintermute/ad/ad_scene.cpp
+++ b/engines/wintermute/ad/ad_scene.cpp
@@ -2041,6 +2041,10 @@ bool AdScene::scSetProperty(const char *name, ScValue *value) {
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollSpeedX") == 0) {
_scrollTimeH = value->getInt();
+ if (_scrollTimeH == 0) {
+ warning("_scrollTimeH can't be 0, resetting to default");
+ _scrollTimeH = 10;
+ }
return STATUS_OK;
}
@@ -2049,6 +2053,10 @@ bool AdScene::scSetProperty(const char *name, ScValue *value) {
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ScrollSpeedY") == 0) {
_scrollTimeV = value->getInt();
+ if (_scrollTimeV == 0) {
+ warning("_scrollTimeV can't be 0, resetting to default");
+ _scrollTimeV = 10;
+ }
return STATUS_OK;
}
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index b879e789e3..f8eb40d42a 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -271,11 +271,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
//debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
Graphics::Surface *surface = new Graphics::Surface();
- if (_deletableFont) { // We actually have a TTF
- surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat());
- } else { // We are using a fallback, they can't do 32bpp
- surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
- }
+ surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat());
uint32 useColor = 0xffffffff;
Common::Array<WideString>::iterator it;
int heightOffset = 0;
@@ -285,7 +281,6 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
}
BaseSurface *retSurface = _gameRef->_renderer->createSurface();
- Graphics::Surface *convertedSurface = surface->convertTo(_gameRef->_renderer->getPixelFormat());
if (_deletableFont) {
// Reconstruct the alpha channel of the font.
@@ -295,7 +290,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
// to its original alpha value.
Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat();
- uint32 *pixels = (uint32 *)convertedSurface->getPixels();
+ uint32 *pixels = (uint32 *)surface->getPixels();
// This is a Surface we created ourselves, so no empty space between rows.
for (int i = 0; i < surface->w * surface->h; ++i) {
@@ -306,11 +301,9 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
}
}
- retSurface->putSurface(*convertedSurface, true);
- convertedSurface->free();
+ retSurface->putSurface(*surface, true);
surface->free();
delete surface;
- delete convertedSurface;
return retSurface;
// TODO: _isUnderline, _isBold, _isItalic, _isStriked
}
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index c33e8ba54b..cbc32387e1 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -447,7 +447,7 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect,
bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) {
_loaded = true;
- if (surface.format == _surface->format && surface.w == _surface->w && surface.h == _surface->h) {
+ if (surface.format == _surface->format && surface.pitch == _surface->pitch && surface.h == _surface->h) {
const byte *src = (const byte *)surface.getBasePtr(0, 0);
byte *dst = (byte *)_surface->getBasePtr(0, 0);
memcpy(dst, src, surface.pitch * surface.h);
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index 299b64f915..3bce8628b8 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -305,7 +305,7 @@ bool VideoTheoraPlayer::update() {
if (!_theoraDecoder->endOfVideo() && _theoraDecoder->getTimeToNextFrame() == 0) {
const Graphics::Surface *decodedFrame = _theoraDecoder->decodeNextFrame();
if (decodedFrame) {
- if (decodedFrame->format == _surface.format && decodedFrame->w == _surface.w && decodedFrame->h == _surface.h) {
+ if (decodedFrame->format == _surface.format && decodedFrame->pitch == _surface.pitch && decodedFrame->h == _surface.h) {
const byte *src = (const byte *)decodedFrame->getBasePtr(0, 0);
byte *dst = (byte *)_surface.getBasePtr(0, 0);
memcpy(dst, src, _surface.pitch * _surface.h);