aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/cge/POTFILES2
-rw-r--r--engines/cge/detection.cpp74
-rw-r--r--engines/cge/fileio.cpp22
-rw-r--r--engines/cge2/POTFILES1
-rw-r--r--engines/cge2/cge2.cpp3
-rw-r--r--engines/cge2/cge2.h7
-rw-r--r--engines/cge2/cge2_main.cpp15
-rw-r--r--engines/cge2/detection.cpp87
-rw-r--r--engines/cge2/fileio.cpp14
-rw-r--r--engines/cge2/hero.cpp18
-rw-r--r--engines/cge2/map.cpp2
-rw-r--r--engines/cge2/saveload.cpp4
-rw-r--r--engines/cge2/snail.cpp2
-rw-r--r--engines/cge2/sound.cpp6
-rw-r--r--engines/cge2/toolbar.cpp17
-rw-r--r--engines/cge2/vga13h.cpp3
-rw-r--r--engines/drascula/drascula.cpp14
-rw-r--r--engines/dreamweb/POTFILES2
-rw-r--r--engines/fullpipe/scenes/scene27.cpp2
-rw-r--r--engines/gob/POTFILES2
-rw-r--r--engines/gob/inter_v1.cpp2
-rw-r--r--engines/hopkins/POTFILES2
-rw-r--r--engines/hopkins/files.cpp2
-rw-r--r--engines/kyra/POTFILES1
-rw-r--r--engines/kyra/detection_tables.h16
-rw-r--r--engines/kyra/items_lol.cpp2
-rw-r--r--engines/kyra/staticres.cpp2
-rw-r--r--engines/kyra/staticres_eob.cpp28
-rw-r--r--engines/kyra/text_rpg.cpp4
-rw-r--r--engines/mads/animation.cpp84
-rw-r--r--engines/mads/animation.h25
-rw-r--r--engines/mads/audio.cpp43
-rw-r--r--engines/mads/audio.h1
-rw-r--r--engines/mads/debugger.cpp43
-rw-r--r--engines/mads/debugger.h2
-rw-r--r--engines/mads/dialogs.cpp74
-rw-r--r--engines/mads/dialogs.h32
-rw-r--r--engines/mads/game.cpp2
-rw-r--r--engines/mads/mads.cpp5
-rw-r--r--engines/mads/menu_views.cpp768
-rw-r--r--engines/mads/menu_views.h225
-rw-r--r--engines/mads/module.mk1
-rw-r--r--engines/mads/msurface.cpp9
-rw-r--r--engines/mads/msurface.h5
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp89
-rw-r--r--engines/mads/nebular/dialogs_nebular.h32
-rw-r--r--engines/mads/nebular/game_nebular.cpp26
-rw-r--r--engines/mads/nebular/game_nebular.h4
-rw-r--r--engines/mads/nebular/menu_nebular.cpp559
-rw-r--r--engines/mads/nebular/menu_nebular.h129
-rw-r--r--engines/mads/nebular/nebular_scenes5.cpp2
-rw-r--r--engines/mads/nebular/nebular_scenes6.cpp5
-rw-r--r--engines/mads/nebular/sound_nebular.cpp55
-rw-r--r--engines/mads/nebular/sound_nebular.h27
-rw-r--r--engines/mads/palette.cpp63
-rw-r--r--engines/mads/palette.h2
-rw-r--r--engines/mads/phantom/game_phantom.cpp15
-rw-r--r--engines/mads/scene.cpp3
-rw-r--r--engines/mads/scene.h10
-rw-r--r--engines/mads/scene_data.cpp39
-rw-r--r--engines/mads/scene_data.h3
-rw-r--r--engines/mads/screen.cpp2
-rw-r--r--engines/mads/sound.cpp37
-rw-r--r--engines/mads/sound.h1
-rw-r--r--engines/mads/sprites.cpp6
-rw-r--r--engines/mads/user_interface.h2
-rw-r--r--engines/prince/animation.cpp178
-rw-r--r--engines/prince/animation.h73
-rw-r--r--engines/prince/archive.cpp144
-rw-r--r--engines/prince/archive.h61
-rw-r--r--engines/prince/common.h45
-rw-r--r--engines/prince/configure.engine3
-rw-r--r--engines/prince/cursor.cpp54
-rw-r--r--engines/prince/cursor.h46
-rw-r--r--engines/prince/curve_values.h45
-rw-r--r--engines/prince/debugger.cpp174
-rw-r--r--engines/prince/debugger.h58
-rw-r--r--engines/prince/decompress.cpp171
-rw-r--r--engines/prince/decompress.h44
-rw-r--r--engines/prince/detection.cpp73
-rw-r--r--engines/prince/detection.h100
-rw-r--r--engines/prince/flags.cpp420
-rw-r--r--engines/prince/flags.h421
-rw-r--r--engines/prince/font.cpp94
-rw-r--r--engines/prince/font.h64
-rw-r--r--engines/prince/graphics.cpp474
-rw-r--r--engines/prince/graphics.h76
-rw-r--r--engines/prince/hero.cpp1002
-rw-r--r--engines/prince/hero.h184
-rw-r--r--engines/prince/hero_set.h244
-rw-r--r--engines/prince/mhwanh.cpp71
-rw-r--r--engines/prince/mhwanh.h55
-rw-r--r--engines/prince/mob.cpp108
-rw-r--r--engines/prince/mob.h70
-rw-r--r--engines/prince/module.mk30
-rw-r--r--engines/prince/musNum.h87
-rw-r--r--engines/prince/object.cpp113
-rw-r--r--engines/prince/object.h70
-rw-r--r--engines/prince/option_text.h85
-rw-r--r--engines/prince/prince.cpp4733
-rw-r--r--engines/prince/prince.h668
-rw-r--r--engines/prince/pscr.cpp75
-rw-r--r--engines/prince/pscr.h48
-rw-r--r--engines/prince/resource.h100
-rw-r--r--engines/prince/saveload.cpp514
-rw-r--r--engines/prince/script.cpp2071
-rw-r--r--engines/prince/script.h397
-rw-r--r--engines/prince/sound.cpp211
-rw-r--r--engines/prince/sound.h67
-rw-r--r--engines/prince/variatxt.cpp55
-rw-r--r--engines/prince/variatxt.h40
-rw-r--r--engines/queen/POTFILES2
-rw-r--r--engines/queen/logic.cpp6
-rw-r--r--engines/queen/talk.cpp12
-rw-r--r--engines/saga/actor.h1
-rw-r--r--engines/saga/saveload.cpp29
-rw-r--r--engines/saga/scene.h3
-rw-r--r--engines/saga/sfuncs.cpp4
-rw-r--r--engines/saga/shorten.cpp2
-rw-r--r--engines/sci/console.cpp1
-rw-r--r--engines/sci/detection.cpp22
-rw-r--r--engines/sci/detection_tables.h13
-rw-r--r--engines/sci/engine/kfile.cpp20
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/event.cpp2
-rw-r--r--engines/sci/graphics/frameout.cpp9
-rw-r--r--engines/sci/graphics/palette.cpp24
-rw-r--r--engines/sci/graphics/palette.h2
-rw-r--r--engines/sci/graphics/view.cpp1
-rw-r--r--engines/sci/parser/vocabulary.cpp5
-rw-r--r--engines/sci/resource.cpp52
-rw-r--r--engines/sci/resource.h16
-rw-r--r--engines/sci/resource_audio.cpp1
-rw-r--r--engines/sci/sci.h6
-rw-r--r--engines/sci/sound/drivers/midi.cpp74
-rw-r--r--engines/scumm/POTFILES3
-rw-r--r--engines/scumm/detection.cpp6
-rw-r--r--engines/scumm/detection_tables.h20
-rw-r--r--engines/scumm/object.cpp1
-rw-r--r--engines/scumm/players/player_mac.cpp1
-rw-r--r--engines/scumm/scumm-md5.h9
-rw-r--r--engines/sword1/POTFILES2
-rw-r--r--engines/sword1/console.cpp23
-rw-r--r--engines/sword1/console.h1
-rw-r--r--engines/sword1/sound.cpp65
-rw-r--r--engines/sword1/sound.h2
-rw-r--r--engines/sword1/sword1.cpp2
-rw-r--r--engines/sword1/sword1.h1
-rw-r--r--engines/sword25/kernel/persistenceservice.cpp2
-rw-r--r--engines/sword25/util/pluto/pluto.cpp29
-rw-r--r--engines/tinsel/tinsel.cpp15
-rw-r--r--engines/touche/detection.cpp1
-rw-r--r--engines/tsage/POTFILES3
-rw-r--r--engines/tsage/blue_force/blueforce_dialogs.cpp2
-rw-r--r--engines/tsage/debugger.cpp6
-rw-r--r--engines/tsage/debugger.h4
-rw-r--r--engines/tsage/module.mk3
-rw-r--r--engines/tsage/ringworld/ringworld_dialogs.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_airduct.cpp909
-rw-r--r--engines/tsage/ringworld2/ringworld2_airduct.h89
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp8
-rw-r--r--engines/tsage/ringworld2/ringworld2_outpost.cpp4700
-rw-r--r--engines/tsage/ringworld2/ringworld2_outpost.h259
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.cpp7254
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.h401
-rw-r--r--engines/tsage/ringworld2/ringworld2_vampire.cpp1821
-rw-r--r--engines/tsage/ringworld2/ringworld2_vampire.h179
-rw-r--r--engines/wintermute/POTFILES1
-rw-r--r--engines/wintermute/base/sound/base_sound.cpp18
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.cpp29
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.h15
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.cpp8
-rw-r--r--engines/zvision/POTFILES1
-rw-r--r--engines/zvision/fonts/truetype_font.cpp1
175 files changed, 24028 insertions, 8881 deletions
diff --git a/engines/cge/POTFILES b/engines/cge/POTFILES
new file mode 100644
index 0000000000..55430683c3
--- /dev/null
+++ b/engines/cge/POTFILES
@@ -0,0 +1,2 @@
+engines/cge/detection.cpp
+
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 022ff4df95..da5eb2b1f2 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -28,35 +28,19 @@
#include "base/plugins.h"
#include "graphics/thumbnail.h"
#include "cge/cge.h"
+#include "cge/fileio.h"
namespace CGE {
-struct CgeGameDescription {
- ADGameDescription desc;
-};
-
#define GAMEOPTION_COLOR_BLIND_DEFAULT_OFF GUIO_GAMEOPTIONS1
-} // End of namespace CGE
-
static const PlainGameDescriptor CGEGames[] = {
{ "soltys", "Soltys" },
{ 0, 0 }
};
-namespace CGE {
-
static const ADGameDescription gameDescriptions[] = {
{
- "soltys", "",
- {
- {"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
- {"vol.dat", 0, "f9ae2e7f8f7cac91378cdafca43faf1e", 8437572},
- AD_LISTEND
- },
- Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
- },
- {
"soltys", "Freeware",
{
{"vol.cat", 0, "0c33e2c304821a2444d297fc5e2d67c6", 50176},
@@ -114,12 +98,6 @@ static const ADGameDescription gameDescriptions[] = {
AD_TABLE_END_MARKER
};
-static const ADFileBasedFallback fileBasedFallback[] = {
- { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
- { 0, { 0 } }
-};
-} // End of namespace CGE
-
static const ADExtraGuiOptionsMap optionsList[] = {
{
GAMEOPTION_COLOR_BLIND_DEFAULT_OFF,
@@ -136,14 +114,10 @@ static const ADExtraGuiOptionsMap optionsList[] = {
class CGEMetaEngine : public AdvancedMetaEngine {
public:
- CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(CGE::CgeGameDescription), CGEGames, optionsList) {
+ CGEMetaEngine() : AdvancedMetaEngine(CGE::gameDescriptions, sizeof(ADGameDescription), CGEGames, optionsList) {
_singleid = "soltys";
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- return detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback);
- }
-
virtual const char *getName() const {
return "CGE";
}
@@ -152,6 +126,7 @@ public:
return "Soltys (c) 1994-1996 L.K. Avalon";
}
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual int getMaximumSaveSlot() const;
@@ -160,6 +135,44 @@ public:
virtual void removeSaveState(const char *target, int slot) const;
};
+static const ADFileBasedFallback fileBasedFallback[] = {
+ { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
+ { 0, { 0 } }
+};
+
+static ADGameDescription s_fallbackDesc = {
+ "Soltys",
+ "Unknown version",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+};
+
+const ADGameDescription *CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADFilePropertiesMap filesProps;
+
+ const ADGameDescription *game;
+ game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback, &filesProps);
+
+ if (!game)
+ return nullptr;
+
+ SearchMan.clear();
+ SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+ ResourceManager *resman;
+ resman = new ResourceManager();
+ bool result = resman->exist("CGE.SAY");
+ delete resman;
+
+ if (!result)
+ return nullptr;
+
+ reportUnknown(fslist.begin()->getParent(), filesProps);
+ return &s_fallbackDesc;
+}
+
bool CGEMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
@@ -269,9 +282,10 @@ bool CGEMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
}
return desc != 0;
}
+} // End of namespace CGE
#if PLUGIN_ENABLED_DYNAMIC(CGE)
- REGISTER_PLUGIN_DYNAMIC(CGE, PLUGIN_TYPE_ENGINE, CGEMetaEngine);
+REGISTER_PLUGIN_DYNAMIC(CGE, PLUGIN_TYPE_ENGINE, CGE::CGEMetaEngine);
#else
- REGISTER_PLUGIN_STATIC(CGE, PLUGIN_TYPE_ENGINE, CGEMetaEngine);
+REGISTER_PLUGIN_STATIC(CGE, PLUGIN_TYPE_ENGINE, CGE::CGEMetaEngine);
#endif
diff --git a/engines/cge/fileio.cpp b/engines/cge/fileio.cpp
index d910e275eb..df5c31d367 100644
--- a/engines/cge/fileio.cpp
+++ b/engines/cge/fileio.cpp
@@ -77,7 +77,7 @@ ResourceManager::ResourceManager() {
_buff[i]._page = new BtPage;
_buff[i]._pageNo = kBtValNone;
_buff[i]._index = -1;
- assert(_buff[i]._page != NULL);
+ assert(_buff[i]._page != nullptr);
}
}
@@ -118,10 +118,16 @@ uint16 ResourceManager::read(byte *buf, uint16 length) {
BtPage *ResourceManager::getPage(int level, uint16 pageId) {
debugC(1, kCGEDebugFile, "ResourceManager::getPage(%d, %d)", level, pageId);
+ if (level >= kBtLevel)
+ return nullptr;
+
if (_buff[level]._pageNo != pageId) {
int32 pos = pageId * kBtSize;
_buff[level]._pageNo = pageId;
- assert(_catFile->size() > pos);
+
+ if (_catFile->size() <= pos)
+ return nullptr;
+
// In the original, there was a check verifying if the
// purpose was to write a new file. This should only be
// to create a new file, thus it was removed.
@@ -146,11 +152,13 @@ BtKeypack *ResourceManager::find(const char *key) {
uint16 nxt = kBtValRoot;
while (!_catFile->eos()) {
BtPage *pg = getPage(lev, nxt);
+ if (!pg)
+ return nullptr;
+
// search
if (pg->_header._down != kBtValNone) {
int i;
for (i = 0; i < pg->_header._count; i++) {
- // Does this work, or does it have to compare the entire buffer?
if (scumm_strnicmp((const char *)key, (const char*)pg->_inner[i]._key, kBtKeySize) < 0)
break;
}
@@ -167,13 +175,17 @@ BtKeypack *ResourceManager::find(const char *key) {
return &pg->_leaf[i];
}
}
- return NULL;
+ return nullptr;
}
bool ResourceManager::exist(const char *name) {
debugC(1, kCGEDebugFile, "ResourceManager::exist(%s)", name);
- return scumm_stricmp(find(name)->_key, name) == 0;
+ BtKeypack* result = find(name);
+ if (!result)
+ return false;
+
+ return scumm_stricmp(result->_key, name) == 0;
}
uint16 ResourceManager::catRead(byte *buf, uint16 length) {
diff --git a/engines/cge2/POTFILES b/engines/cge2/POTFILES
new file mode 100644
index 0000000000..1e904763ec
--- /dev/null
+++ b/engines/cge2/POTFILES
@@ -0,0 +1 @@
+engines/cge2/detection.cpp
diff --git a/engines/cge2/cge2.cpp b/engines/cge2/cge2.cpp
index 8b51dda75e..37d87ba09c 100644
--- a/engines/cge2/cge2.cpp
+++ b/engines/cge2/cge2.cpp
@@ -76,9 +76,10 @@ CGE2Engine::CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription)
_vol[i] = nullptr;
_eventManager = nullptr;
_map = nullptr;
+ _console = nullptr;
_quitFlag = false;
_bitmapPalette = nullptr;
- _startupMode = 1;
+ _gamePhase = kPhaseIntro;
_now = 1;
_sex = 1;
_mouseTop = kWorldHeight / 3;
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
index 8e94683824..50b418f294 100644
--- a/engines/cge2/cge2.h
+++ b/engines/cge2/cge2.h
@@ -93,10 +93,7 @@ struct SavegameHeader;
#define kPowerRef 123
#define kDvolRef 124
#define kMvolRef 125
-#define kRef 126
#define kBusyRef 127
-#define kCapRef 128
-#define kVoxRef 129
#define kOffUseCount 130
#define kOffUseText 131
@@ -124,6 +121,8 @@ struct SavegameHeader {
enum ColorBank { kCBRel, kCBStd, kCBSay, kCBInf, kCBMnu, kCBWar };
+enum GamePhase { kPhaseInGame, kPhaseIntro, kPhaseOver };
+
// our engine debug channels
enum {
kCGE2DebugOpcode = 1 << 0
@@ -282,7 +281,7 @@ public:
bool _quitFlag;
Dac *_bitmapPalette;
- int _startupMode;
+ GamePhase _gamePhase; // Original name: startupmode
int _now;
int _sex;
int _mouseTop;
diff --git a/engines/cge2/cge2_main.cpp b/engines/cge2/cge2_main.cpp
index c52a354f9e..3e3d615a91 100644
--- a/engines/cge2/cge2_main.cpp
+++ b/engines/cge2/cge2_main.cpp
@@ -49,13 +49,13 @@ void System::touch(uint16 mask, V2D pos, Common::KeyCode keyCode) {
// The original was calling keyClick()
// The sound is uselessly annoying and noisy, so it has been removed
_vm->killText();
- if (_vm->_startupMode == 1) {
+ if (_vm->_gamePhase == kPhaseIntro) {
_vm->_commandHandler->addCommand(kCmdClear, -1, 0, nullptr);
return;
}
}
} else {
- if (_vm->_startupMode)
+ if (_vm->_gamePhase != kPhaseInGame)
return;
_vm->_infoLine->setText(nullptr);
@@ -450,7 +450,7 @@ void CGE2Engine::sceneUp(int cav) {
_dark = false;
- if (!_startupMode)
+ if (_gamePhase == kPhaseInGame)
_mouse->on();
feedSnail(_vga->_showQ->locate(bakRef + 255), kNear, _heroTab[_sex]->_ptr);
@@ -522,7 +522,7 @@ void CGE2Engine::showBak(int ref) {
}
void CGE2Engine::mainLoop() {
- if (_startupMode == 0)
+ if (_gamePhase == kPhaseInGame)
checkSounds();
_vga->show();
@@ -722,10 +722,9 @@ void CGE2Engine::loadTab() {
if (_resman->exist(kTabName)) {
EncryptedStream f(this, kTabName);
- uint32 v;
for (int i = 0; i < kSceneMax; i++) {
- v = f.readUint32LE();
+ uint32 v = f.readUint32LE();
_eyeTab[i]->_x = FXP(v >> 8, static_cast<int>((int8)(v & 0xff)));
v = f.readUint32LE();
@@ -751,7 +750,7 @@ void CGE2Engine::cge2_main() {
if (_text->getText(255) != nullptr) {
runGame();
- _startupMode = 2;
+ _gamePhase = kPhaseOver;
}
_vga->sunset();
@@ -850,7 +849,7 @@ void Sprite::touch(uint16 mask, V2D pos, Common::KeyCode keyCode) {
if ((mask & kEventAttn) != 0)
return;
- if (!_vm->_startupMode)
+ if (_vm->_gamePhase == kPhaseInGame)
_vm->_infoLine->setText(name());
if (_ref < 0)
diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp
index bef640658b..6e1b93d0b8 100644
--- a/engines/cge2/detection.cpp
+++ b/engines/cge2/detection.cpp
@@ -26,6 +26,7 @@
*/
#include "cge2/cge2.h"
+#include "cge2/fileio.h"
#include "engines/advancedDetector.h"
#include "common/translation.h"
#include "graphics/surface.h"
@@ -60,6 +61,26 @@ static const ADGameDescription gameDescriptions[] = {
Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
},
+ {
+ "sfinx", "Freeware v0.3",
+ {
+ {"vol.cat", 0, "f158e469dccbebc5a632eb848df89779", 129024},
+ {"vol.dat", 0, "d40a6b4ae173d6930be54ba56bee15d5", 34183430},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ },
+
+ {
+ "sfinx", "Freeware v1.0",
+ {
+ {"vol.cat", 0, "f158e469dccbebc5a632eb848df89779", 129024},
+ {"vol.dat", 0, "d40a6b4ae173d6930be54ba56bee15d5", 34183443},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ },
+
AD_TABLE_END_MARKER
};
@@ -91,16 +112,55 @@ public:
return "Sfinx (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon";
}
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual int getMaximumSaveSlot() const;
virtual SaveStateList listSaves(const char *target) const;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
virtual void removeSaveState(const char *target, int slot) const;
+};
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+static const ADFileBasedFallback fileBasedFallback[] = {
+ { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
+ { 0, { 0 } }
};
+static ADGameDescription s_fallbackDesc = {
+ "Sfinx",
+ "Unknown version",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+};
+
+// This fallback detection looks identical to the one used for CGE. In fact, the difference resides
+// in the ResourceManager which handles a different archive format. The rest of the detection is identical.
+const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADFilePropertiesMap filesProps;
+
+ const ADGameDescription *game;
+ game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback, &filesProps);
+
+ if (!game)
+ return 0;
+
+ SearchMan.clear();
+ SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+ ResourceManager *resman;
+ resman = new ResourceManager();
+ bool result = resman->exist("CGE.SAY");
+ delete resman;
+
+ if (!result)
+ return 0;
+
+ reportUnknown(fslist.begin()->getParent(), filesProps);
+ return &s_fallbackDesc;
+}
+
bool CGE2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
if (desc)
*engine = new CGE2::CGE2Engine(syst, desc);
@@ -118,31 +178,6 @@ bool CGE2MetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsLoadingDuringStartup);
}
-const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- static ADGameDescription desc;
-
- for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (file->isDirectory())
- continue;
-
- if (file->getName().equalsIgnoreCase("lang.eng")) {
- Common::File dataFile;
- if (!dataFile.open(*file))
- continue;
-
- desc.gameid = "sfinx";
- desc.extra = "Translation Alpha v0.2";
- desc.language = Common::EN_ANY;
- desc.platform = Common::kPlatformDOS;
- desc.flags = ADGF_NO_FLAGS;
- desc.guioptions = GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF);
-
- return (const ADGameDescription *)&desc;
- }
- }
- return 0;
-}
-
int CGE2MetaEngine::getMaximumSaveSlot() const {
return 99;
}
diff --git a/engines/cge2/fileio.cpp b/engines/cge2/fileio.cpp
index 6f8009716b..acb5bb870f 100644
--- a/engines/cge2/fileio.cpp
+++ b/engines/cge2/fileio.cpp
@@ -116,7 +116,10 @@ BtPage *ResourceManager::getPage(int level, uint16 pageId) {
if (_buff[level]._pageNo != pageId) {
int32 pos = pageId * kBtSize;
_buff[level]._pageNo = pageId;
- assert(_catFile->size() > pos);
+
+ if (_catFile->size() <= pos)
+ return nullptr;
+
// In the original, there was a check verifying if the
// purpose was to write a new file. This should only be
// to create a new file, thus it was removed.
@@ -139,6 +142,9 @@ BtKeypack *ResourceManager::find(const char *key) {
uint16 nxt = kBtValRoot;
while (!_catFile->eos()) {
BtPage *pg = getPage(lev, nxt);
+ if (!pg)
+ return nullptr;
+
// search
if (pg->_header._down != kBtValNone) {
int i;
@@ -170,7 +176,11 @@ BtKeypack *ResourceManager::find(const char *key) {
}
bool ResourceManager::exist(const char *name) {
- return scumm_stricmp(find(name)->_key, name) == 0;
+ BtKeypack *result = find(name);
+ if (!result)
+ return false;
+
+ return scumm_stricmp(result->_key, name) == 0;
}
uint16 ResourceManager::catRead(byte *buf, uint16 length) {
diff --git a/engines/cge2/hero.cpp b/engines/cge2/hero.cpp
index 86bd7ac953..225df54bd1 100644
--- a/engines/cge2/hero.cpp
+++ b/engines/cge2/hero.cpp
@@ -31,13 +31,14 @@
namespace CGE2 {
-Hero::Hero(CGE2Engine *vm)
- : Sprite(vm), _contact(nullptr), _dir(kNoDir),
- _curDim(0), _tracePtr(-1), _ignoreMap(false), _maxDist(0) {
+Hero::Hero(CGE2Engine *vm) : Sprite(vm), _contact(nullptr), _dir(kNoDir),
+ _curDim(0), _tracePtr(-1), _ignoreMap(false), _maxDist(0) {
- for (int i = 0; i < kDimMax; i++) {
+ for (int i = 0; i < kDimMax; i++)
_dim[i] = nullptr;
- }
+
+ _reachStart = _reachCycle = _sayStart = _funStart = 0;
+ _funDel0 = _funDel = 0;
}
Hero::~Hero() {
@@ -120,7 +121,8 @@ Sprite *Hero::expand() {
break;
case kIdName:
Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
- for (p = tmpStr; *p != '='; p++); // We search for the =
+ for (p = tmpStr; *p != '='; p++) // We search for the =
+ ;
setName(_vm->tail(p));
break;
default:
@@ -201,7 +203,7 @@ Sprite *Hero::expand() {
delete[] text;
int i = stepSize() / 2;
- _maxDist = sqrt(double(i * i * 2));
+ _maxDist = (int)sqrt(double(i * i * 2));
setCurrent();
return this;
@@ -413,7 +415,7 @@ void Hero::fun() {
}
int Hero::len(V2D v) {
- return sqrt(double(v.x * v.x + v.y * v.y));
+ return (int)sqrt(double(v.x * v.x + v.y * v.y));
}
bool Hero::findWay(){
diff --git a/engines/cge2/map.cpp b/engines/cge2/map.cpp
index 1ed0ea7daf..8c1f00048f 100644
--- a/engines/cge2/map.cpp
+++ b/engines/cge2/map.cpp
@@ -42,7 +42,7 @@ void Map::clear() {
void Map::load(int scene) {
clear();
- char fname[] = "%.2d.MAP\0";
+ const char *fname = "%.2d.MAP";
Common::String fileName = Common::String::format(fname, scene);
if (!_vm->_resman->exist(fileName.c_str()))
return;
diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp
index c9cedff83f..fd60422dff 100644
--- a/engines/cge2/saveload.cpp
+++ b/engines/cge2/saveload.cpp
@@ -45,7 +45,7 @@ namespace CGE2 {
#define kBadSVG 99
bool CGE2Engine::canSaveGameStateCurrently() {
- return (_startupMode == 0) && _mouse->_active &&
+ return (_gamePhase == kPhaseInGame) && _mouse->_active &&
_commandHandler->idle() && (_soundStat._wait == nullptr);
}
@@ -77,7 +77,7 @@ void CGE2Engine::saveGame(int slotNumber, const Common::String &desc) {
}
bool CGE2Engine::canLoadGameStateCurrently() {
- return (_startupMode == 0) && _mouse->_active;
+ return (_gamePhase == kPhaseInGame) && _mouse->_active;
}
Common::Error CGE2Engine::loadGameState(int slot) {
diff --git a/engines/cge2/snail.cpp b/engines/cge2/snail.cpp
index 0bf63839e9..8e1ddf2d9b 100644
--- a/engines/cge2/snail.cpp
+++ b/engines/cge2/snail.cpp
@@ -62,7 +62,7 @@ void CommandHandler::runCommand() {
if (_vm->_fx->exist(_vm->_soundStat._ref[1], _vm->_soundStat._ref[0])) {
int16 oldRepeat = _vm->_sound->getRepeat();
_vm->_sound->setRepeat(1);
- _vm->_sound->play(Audio::Mixer::kSFXSoundType, _vm->_fx->load(_vm->_soundStat._ref[1], _vm->_soundStat._ref[0]), _vm->_sound->_smpinf._span);
+ _vm->_sound->play(Audio::Mixer::kSpeechSoundType, _vm->_fx->load(_vm->_soundStat._ref[1], _vm->_soundStat._ref[0]), _vm->_sound->_smpinf._span);
_vm->_sound->setRepeat(oldRepeat);
return;
}
diff --git a/engines/cge2/sound.cpp b/engines/cge2/sound.cpp
index 32f94b17b9..57ec5983e8 100644
--- a/engines/cge2/sound.cpp
+++ b/engines/cge2/sound.cpp
@@ -143,9 +143,9 @@ void Fx::clear() {
}
Common::String Fx::name(int ref, int sub) {
- char fxname[] = "%.2dfx%.2d.WAV\0";
- char subName[] = "%.2dfx%.2d?.WAV\0";
- char *p = (sub) ? subName : fxname;
+ const char *fxname = "%.2dfx%.2d.WAV";
+ const char *subName = "%.2dfx%.2d?.WAV";
+ const char *p = (sub) ? subName : fxname;
Common::String filename = Common::String::format(p, ref >> 8, ref & 0xFF);
if (sub)
filename.setChar('@' + sub, 6);
diff --git a/engines/cge2/toolbar.cpp b/engines/cge2/toolbar.cpp
index dbbed3480e..0cd220c984 100644
--- a/engines/cge2/toolbar.cpp
+++ b/engines/cge2/toolbar.cpp
@@ -35,11 +35,11 @@
namespace CGE2 {
-#define kSoundNumtoStateRate 25.7
+#define kSoundNumToStateRate 25.7
// == 257 / 10; where 10 equals to the volume switches' number of states [0..9]
// and ScummVM has a scale of 257 different values for setting sounds.
-#define kSoundStatetoNumRate 28.45
+#define kSoundStateToNumRate 28.45
// == 256 / 9 + 0.1; where 256 is the positive range of numbers we can set the volume to
// and the 10 states of a switch cut this range up to 9 equally big parts.
// We don't take into account 0 regarding the 256 different values (it would be the 257th),
@@ -120,7 +120,7 @@ void CGE2Engine::setVolume(int idx, int cnt) {
int p = _vol[idx]->_seqPtr + cnt;
if ((p >= 0) && (p < _vol[idx]->_seqCnt)) {
_vol[idx]->step(p);
- int newVolume = p * kSoundStatetoNumRate;
+ int newVolume = (int)(p * kSoundStateToNumRate);
switch (idx) {
case 0:
_oldSfxVolume = ConfMan.getInt("sfx_volume");
@@ -140,11 +140,11 @@ void CGE2Engine::setVolume(int idx, int cnt) {
void CGE2Engine::checkVolumeSwitches() {
int musicVolume = ConfMan.getInt("music_volume");
if (musicVolume != _oldMusicVolume)
- _vol[1]->step(musicVolume / kSoundNumtoStateRate);
+ _vol[1]->step((int)(musicVolume / kSoundNumToStateRate));
int sfxVolume = ConfMan.getInt("sfx_volume");
if (sfxVolume != _oldSfxVolume)
- _vol[0]->step(sfxVolume / kSoundNumtoStateRate);
+ _vol[0]->step((int)(sfxVolume / kSoundNumToStateRate));
}
void CGE2Engine::switchCap() {
@@ -182,7 +182,7 @@ void CGE2Engine::initToolbar() {
_infoLine->setText(nullptr);
_vga->_showQ->insert(_infoLine);
- _startupMode = 0;
+ _gamePhase = kPhaseInGame;
_mouse->center();
_mouse->off();
_mouse->on();
@@ -208,14 +208,13 @@ void CGE2Engine::initToolbar() {
void CGE2Engine::initVolumeSwitch(Sprite *volSwitch, int val) {
int state = 0;
- state = val / kSoundNumtoStateRate;
+ state = (int)(val / kSoundNumToStateRate);
volSwitch->step(state);
}
void CGE2Engine::checkMute() {
bool mute = ConfMan.getBool("mute");
- bool mutedChanged = mute != _muteAll;
- if (mutedChanged) {
+ if (mute != _muteAll) {
switchMusic();
switchVox();
_muteAll = mute;
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
index db96682237..227633579e 100644
--- a/engines/cge2/vga13h.cpp
+++ b/engines/cge2/vga13h.cpp
@@ -371,7 +371,8 @@ Sprite *Sprite::expand() {
break;
case kIdName:
Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
- for (p = tmpStr; *p != '='; p++); // We search for the =
+ for (p = tmpStr; *p != '='; p++) // We search for the =
+ ;
setName(_vm->tail(p));
break;
default:
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index 797b6d94b0..c72d77c281 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -41,20 +41,6 @@
namespace Drascula {
-struct GameSettings {
- const char *gameid;
- const char *description;
- byte id;
- uint32 features;
- const char *detectname;
-};
-
-static const GameSettings drasculaSettings[] = {
- {"drascula", "Drascula game", 0, 0, 0},
-
- {NULL, NULL, 0, 0, NULL}
-};
-
DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
_charMap = 0;
_itemLocations = 0;
diff --git a/engines/dreamweb/POTFILES b/engines/dreamweb/POTFILES
index d05d239bb7..64fb20db67 100644
--- a/engines/dreamweb/POTFILES
+++ b/engines/dreamweb/POTFILES
@@ -1 +1,3 @@
engines/dreamweb/detection.cpp
+engines/dreamweb/saveload.cpp
+
diff --git a/engines/fullpipe/scenes/scene27.cpp b/engines/fullpipe/scenes/scene27.cpp
index 1431ceffba..8ec05caaff 100644
--- a/engines/fullpipe/scenes/scene27.cpp
+++ b/engines/fullpipe/scenes/scene27.cpp
@@ -340,7 +340,7 @@ void sceneHandler27_wipeDo() {
bool sceneHandler27_batFallLogic(uint batn) {
Bat *bat = g_vars->scene27_bats[batn];
- int y = (bat->currY - 458.0) * 0.4848484848484849 + 734.0;
+ int y = (int)((bat->currY - 458.0) * 0.4848484848484849 + 734.0);
if (y >= bat->currX)
return false;
diff --git a/engines/gob/POTFILES b/engines/gob/POTFILES
index 9a512469dd..ca7aa14177 100644
--- a/engines/gob/POTFILES
+++ b/engines/gob/POTFILES
@@ -1,3 +1,5 @@
engines/gob/inter_playtoons.cpp
engines/gob/inter_v2.cpp
engines/gob/inter_v5.cpp
+engines/gob/inter_geisha.cpp
+
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 40134bbf17..676564a9fb 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1124,8 +1124,6 @@ void Inter_v1::o1_palLoad(OpFuncParams &params) {
_vm->_draw->_vgaPalette[i].green = _vm->_game->_script->readByte();
_vm->_draw->_vgaPalette[i].blue = _vm->_game->_script->readByte();
}
-
- memcpy(_vm->_draw->_vgaPalette, _vm->_draw->_vgaPalette, 16 * 3);
break;
case 53:
diff --git a/engines/hopkins/POTFILES b/engines/hopkins/POTFILES
new file mode 100644
index 0000000000..1ea7d5111b
--- /dev/null
+++ b/engines/hopkins/POTFILES
@@ -0,0 +1,2 @@
+engines/hopkins/detection.cpp
+
diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp
index 6620f2878c..3100ed6cdc 100644
--- a/engines/hopkins/files.cpp
+++ b/engines/hopkins/files.cpp
@@ -74,7 +74,7 @@ int FileManager::readStream(Common::ReadStream &stream, void *buf, size_t nbytes
* It's now using the config manager and a per-engine GUI option.
*/
void FileManager::initCensorship() {
- _vm->_globals->_censorshipFl = ConfMan.getBool("enable_gore");
+ _vm->_globals->_censorshipFl = !ConfMan.getBool("enable_gore");
}
/**
diff --git a/engines/kyra/POTFILES b/engines/kyra/POTFILES
index 16888e2c5a..e5b380e52e 100644
--- a/engines/kyra/POTFILES
+++ b/engines/kyra/POTFILES
@@ -1,3 +1,4 @@
engines/kyra/detection.cpp
engines/kyra/lol.cpp
engines/kyra/sound_midi.cpp
+engines/kyra/saveload_eob.cpp
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index 1ada9a87ba..2ee0262ef2 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -1568,6 +1568,22 @@ const KYRAGameDescription adGameDescs[] = {
EOB_FLAGS
},
+ { // Italian fan translation
+ {
+ "eob",
+ 0,
+ {
+ { "EOBDATA3.PAK", 0, "3ed915ab5b94d60dbfe1b55379889c51", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_TESTING,
+ GUIO7(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK, GUIO_RENDERVGA, GUIO_RENDEREGA, GUIO_RENDERCGA, GAMEOPTION_EOB_HPGRAPHS)
+ },
+ EOB_FLAGS
+ },
+
{
{
"eob2",
diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp
index f2a9637dfe..e1f864ddd2 100644
--- a/engines/kyra/items_lol.cpp
+++ b/engines/kyra/items_lol.cpp
@@ -265,7 +265,7 @@ bool LoLEngine::addItemToInventory(Item itemIndex) {
gui_drawInventory();
}
- assert(pos > 0 && pos < 48);
+ assert(pos >= 0 && pos < 48);
_inventory[pos] = itemIndex;
gui_drawInventory();
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 9b3b92b9c7..731f2f4ce5 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -39,7 +39,7 @@
namespace Kyra {
-#define RESFILE_VERSION 85
+#define RESFILE_VERSION 86
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp
index 54cc3066ec..aa7adc7461 100644
--- a/engines/kyra/staticres_eob.cpp
+++ b/engines/kyra/staticres_eob.cpp
@@ -464,20 +464,34 @@ void EoBCoreEngine::initStaticResource() {
// EOB I doesn't have load and save menus, because there is only one single
// save slot. Instead of emulating this we provide a menu similiar to EOB II.
- static const char *const saveLoadStrings[3][4] = {
- { "Cancel", "Empty Slot", "Save Game", "Load Game" },
- { "Abbr.", "Leerer Slot", "Speichern", " Laden" },
- { 0, 0, 0, 0 }
+ static const char *const saveLoadStrings[4][4] = {
+ { "Cancel", "Empty Slot", "Save Game", "Load Game" },
+ { "Abbr.", "Leerer Slot", "Speichern", " Laden" },
+ { " < < ", "Posizione Vuota", "Salva", "Carica" },
+ { 0, 0, 0, 0 }
};
- static const char *const errorSlotEmptyString[3] = {
+ static const char *const errorSlotEmptyString[4] = {
"There is no game\rsaved in that slot!",
"Hier ist noch kein\rSpiel gespeichert!",
+ "Non c'\x0E alcun gioco\rsalvato in quella\rposizione!",
0
};
- _saveLoadStrings = saveLoadStrings[(_flags.lang == Common::EN_ANY) ? 0 : ((_flags.lang == Common::DE_DEU) ? 1 : 2)];
- _errorSlotEmptyString = errorSlotEmptyString[(_flags.lang == Common::EN_ANY) ? 0 : ((_flags.lang == Common::DE_DEU) ? 1 : 2)];
+ if (_flags.lang == Common::EN_ANY) {
+ _saveLoadStrings = saveLoadStrings[0];
+ _errorSlotEmptyString = errorSlotEmptyString[0];
+ } else if (_flags.lang == Common::DE_DEU) {
+ _saveLoadStrings = saveLoadStrings[1];
+ _errorSlotEmptyString = errorSlotEmptyString[1];
+ } else if (_flags.lang == Common::IT_ITA) {
+ _saveLoadStrings = saveLoadStrings[2];
+ _errorSlotEmptyString = errorSlotEmptyString[2];
+ } else {
+ _saveLoadStrings = saveLoadStrings[3];
+ _errorSlotEmptyString = errorSlotEmptyString[3];
+ }
+
_menuOkString = "OK";
}
diff --git a/engines/kyra/text_rpg.cpp b/engines/kyra/text_rpg.cpp
index 03acde8497..5cd99738ef 100644
--- a/engines/kyra/text_rpg.cpp
+++ b/engines/kyra/text_rpg.cpp
@@ -30,7 +30,7 @@
namespace Kyra {
enum {
- kEoBTextBufferSize = 2048
+ kEoBTextBufferSize = 2560
};
TextDisplayer_rpg::TextDisplayer_rpg(KyraRpgEngine *engine, Screen *scr) : _vm(engine), _screen(scr),
@@ -216,7 +216,7 @@ void TextDisplayer_rpg::displayText(char *str, ...) {
break;
default:
- if (_vm->game() == GI_LOL || (unsigned char)c > 30) {
+ if (_vm->game() == GI_EOB1 || _vm->game() == GI_LOL || (unsigned char)c > 30) {
_lineWidth += (sjisTextMode ? 4 : (_screen->_currentFont == Screen::FID_SJIS_FNT ? 9 : _screen->getCharWidth((uint8)c)));
_currentLine[_numCharsLeft++] = c;
_currentLine[_numCharsLeft] = 0;
diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp
index 512a3979f9..2b999fa305 100644
--- a/engines/mads/animation.cpp
+++ b/engines/mads/animation.cpp
@@ -32,10 +32,8 @@ void AAHeader::load(Common::SeekableReadStream *f) {
_miscEntriesCount = f->readUint16LE();
_frameEntriesCount = f->readUint16LE();
_messagesCount = f->readUint16LE();
- f->skip(1);
- _flags = f->readByte();
-
- f->skip(2);
+ _loadFlags = f->readUint16LE();
+ _charSpacing = f->readSint16LE();
_bgType = (AnimBgType)f->readUint16LE();
_roomNumber = f->readUint16LE();
f->skip(2);
@@ -49,7 +47,7 @@ void AAHeader::load(Common::SeekableReadStream *f) {
char buffer[FILENAME_SIZE];
f->read(buffer, FILENAME_SIZE);
buffer[FILENAME_SIZE - 1] = '\0';
- _interfaceFile = Common::String(buffer);
+ _backgroundFile = Common::String(buffer);
for (int i = 0; i < 50; ++i) {
f->read(buffer, FILENAME_SIZE);
@@ -134,7 +132,8 @@ void AnimMiscEntry::load(Common::SeekableReadStream *f) {
_numTicks = f->readUint16LE();
_posAdjust.x = f->readSint16LE();
_posAdjust.y = f->readSint16LE();
- _field8 = f->readUint16LE();
+ _scroll.x = f->readSByte();
+ _scroll.y = f->readSByte();
}
/*------------------------------------------------------------------------*/
@@ -160,6 +159,7 @@ Animation *Animation::init(MADSEngine *vm, Scene *scene) {
}
Animation::Animation(MADSEngine *vm, Scene *scene) : _vm(vm), _scene(scene) {
+ _flags = 0;
_font = nullptr;
_resetFlag = false;
_messageCtr = 0;
@@ -175,6 +175,8 @@ Animation::Animation(MADSEngine *vm, Scene *scene) : _vm(vm), _scene(scene) {
_actionDetails._indirectObjectId = -1;
_currentFrame = 0;
_oldFrameEntry = 0;
+ _rgbResult = -1;
+ _palIndex1 = _palIndex2 = -1;
}
Animation::~Animation() {
@@ -189,7 +191,7 @@ Animation::~Animation() {
}
}
-void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface,
+void Animation::load(MSurface &backSurface, DepthSurface &depthSurface,
const Common::String &resName, int flags, Common::Array<PaletteCycle> *palCycles,
SceneInfo *sceneInfo) {
Common::String resourceName = resName;
@@ -205,9 +207,10 @@ void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface
if (_header._bgType == ANIMBG_INTERFACE)
flags |= PALFLAG_RESERVED;
+ _flags = flags;
if (flags & ANIMFLAG_LOAD_BACKGROUND) {
- loadInterface(interfaceSurface, depthSurface, _header, flags, palCycles, sceneInfo);
+ loadBackground(backSurface, depthSurface, _header, flags, palCycles, sceneInfo);
}
if (flags & ANIMFLAG_LOAD_BACKGROUND_ONLY) {
// No data
@@ -243,7 +246,7 @@ void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface
for (int i = 0; i < _header._frameEntriesCount; i++) {
AnimFrameEntry rec;
- rec.load(frameStream, flags & ANIMFLAG_LOAD_BACKGROUND);
+ rec.load(frameStream, _header._bgType == ANIMBG_INTERFACE);
_frameEntries.push_back(rec);
}
@@ -256,7 +259,7 @@ void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface
// Chunk 4: Misc Data
Common::SeekableReadStream *miscStream = madsPack.getItemStream(streamIndex++);
- if (flags & ANIMFLAG_LOAD_BACKGROUND) {
+ if (_header._bgType == ANIMBG_INTERFACE) {
for (int i = 0; i < _header._miscEntriesCount; ++i) {
AnimUIEntry rec;
rec.load(miscStream);
@@ -275,7 +278,7 @@ void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface
// If the animation specifies a font, then load it for access
delete _font;
- if (_header._flags & ANIMFLAG_CUSTOM_FONT) {
+ if (_header._loadFlags & ANIMFLAG_CUSTOM_FONT) {
Common::String fontName = "*" + _header._fontResource;
_font = _vm->_font->getFont(fontName.c_str());
} else {
@@ -337,9 +340,6 @@ void Animation::startAnimation(int endTrigger) {
_unkIndex = -1;
//SpriteAsset *asset = _scene->_sprites[_spriteListIndexes[_header._spritesIndex]];
- // TODO: Weird stuff with _unkList. Seems like it's treated as pointers
- // here, but in processText, it's used as POINTs?
-
loadFrame(1);
}
@@ -385,12 +385,12 @@ bool Animation::drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int f
return 0;
}
-void Animation::loadInterface(UserInterface &interfaceSurface, DepthSurface &depthSurface,
+void Animation::loadBackground(MSurface &backSurface, DepthSurface &depthSurface,
AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo) {
_scene->_depthStyle = 0;
if (header._bgType <= ANIMBG_FULL_SIZE) {
_vm->_palette->_paletteUsage.setEmpty();
- sceneInfo->load(header._roomNumber, flags, header._interfaceFile, 0, depthSurface, interfaceSurface);
+ sceneInfo->load(header._roomNumber, 0, header._backgroundFile, flags, depthSurface, backSurface);
_scene->_depthStyle = sceneInfo->_depthStyle == 2 ? 1 : 0;
if (palCycles) {
palCycles->clear();
@@ -399,8 +399,8 @@ void Animation::loadInterface(UserInterface &interfaceSurface, DepthSurface &dep
}
} else if (header._bgType == ANIMBG_INTERFACE) {
// Load a scene interface
- Common::String resourceName = "*" + header._interfaceFile;
- interfaceSurface.load(resourceName);
+ Common::String resourceName = "*" + header._backgroundFile;
+ backSurface.load(resourceName);
if (palCycles)
palCycles->clear();
@@ -415,6 +415,7 @@ bool Animation::hasScroll() const {
void Animation::update() {
Scene &scene = _vm->_game->_scene;
+ Palette &palette = *_vm->_palette;
if (_header._manualFlag) {
int spriteListIndex = _spriteListIndexes[_header._spritesIndex];
@@ -534,28 +535,43 @@ void Animation::update() {
// Start displaying the message
AnimMessage &me = _messages[idx];
- // The color index to use is dependant on how many messages are currently on-screen
- uint8 colIndex;
- switch (_messageCtr) {
- case 1:
- colIndex = 252;
- break;
- case 2:
- colIndex = 16;
- break;
- default:
- colIndex = 250;
- break;
- }
+ if (_flags & ANIMFLAG_ANIMVIEW) {
+ _rgbResult = palette._paletteUsage.checkRGB(me._rgb1, -1, true, &_palIndex1);
+ _rgbResult = palette._paletteUsage.checkRGB(me._rgb2, _rgbResult, true, &_palIndex2);
+
+ // Update the palette with the two needed colors
+ int palStart = MIN(_palIndex1, _palIndex2);
+ int palCount = ABS(_palIndex2 - _palIndex1) + 1;
+ palette.setPalette(&palette._mainPalette[palStart * 3], palStart, palCount);
+ } else {
+ // The color index to use is dependant on how many messages are currently on-screen
+ switch (_messageCtr) {
+ case 1:
+ _palIndex1 = 252;
+ break;
+ case 2:
+ _palIndex1 = 16;
+ break;
+ default:
+ _palIndex1 = 250;
+ break;
+ }
+ _palIndex2 = _palIndex1 + 1;
- _vm->_palette->setEntry(colIndex, me._rgb1[0], me._rgb1[1], me._rgb1[2]);
- _vm->_palette->setEntry(colIndex + 1, me._rgb2[0], me._rgb2[1], me._rgb2[2]);
+ _vm->_palette->setEntry(_palIndex1, me._rgb1[0], me._rgb1[1], me._rgb1[2]);
+ _vm->_palette->setEntry(_palIndex2, me._rgb2[0], me._rgb2[1], me._rgb2[2]);
+ }
// Add a kernel message to display the given text
- me._kernelMsgIndex = scene._kernelMessages.add(me._pos, colIndex * 0x101 + 0x100,
+ me._kernelMsgIndex = scene._kernelMessages.add(me._pos,
+ _palIndex1 | (_palIndex2 << 8),
0, 0, INDEFINITE_TIMEOUT, me._msg);
assert(me._kernelMsgIndex >= 0);
++_messageCtr;
+
+ // If there's an accompanying sound, also play it
+ if (me._soundId > 0)
+ _vm->_audio->playSound(me._soundId - 1);
}
}
diff --git a/engines/mads/animation.h b/engines/mads/animation.h
index 15086d3e41..8b85a5370d 100644
--- a/engines/mads/animation.h
+++ b/engines/mads/animation.h
@@ -34,10 +34,11 @@
namespace MADS {
enum AnimFlag {
- ANIMFLAG_DITHER = 0x0001, // Dither to 16 colors
- ANIMFLAG_CUSTOM_FONT = 0x0020, // Load ccustom font
+ ANIMFLAG_DITHER = 0x1000, // Dither to 16 colors
+ ANIMFLAG_CUSTOM_FONT = 0x2000, // Load ccustom font
ANIMFLAG_LOAD_BACKGROUND = 0x0100, // Load background
- ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200 // Load background only
+ ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200, // Load background only
+ ANIMFLAG_ANIMVIEW = 0x4000 // Cutscene animation
};
enum AnimBgType {
@@ -82,7 +83,7 @@ public:
int _msgIndex;
int _numTicks;
Common::Point _posAdjust;
- int _field8;
+ Common::Point _scroll;
/**
* Loads data for the record
@@ -116,14 +117,15 @@ public:
int _miscEntriesCount;
int _frameEntriesCount;
int _messagesCount;
- byte _flags;
+ int _loadFlags;
+ int _charSpacing;
AnimBgType _bgType;
int _roomNumber;
bool _manualFlag;
int _spritesIndex;
Common::Point _scrollPosition;
uint32 _scrollTicks;
- Common::String _interfaceFile;
+ Common::String _backgroundFile;
Common::StringArray _spriteSetNames;
Common::String _lbmFilename;
Common::String _spritesFilename;
@@ -154,6 +156,9 @@ private:
uint32 _nextScrollTimer;
int _messageCtr;
int _trigger;
+ int _flags;
+ int _rgbResult;
+ int _palIndex1, _palIndex2;
TriggerMode _triggerMode;
ActionDetails _actionDetails;
@@ -166,9 +171,9 @@ private:
bool drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
/**
- * Load the user interface display for an animation
+ * Load the user interface display or background for an animation
*/
- void loadInterface(UserInterface &interfaceSurface, DepthSurface &depthSurface,
+ void loadBackground(MSurface &backSurface, DepthSurface &depthSurface,
AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo);
/**
@@ -196,7 +201,7 @@ public:
/**
* Loads animation data
*/
- void load(UserInterface &interfaceSurface, DepthSurface &depthSurface, const Common::String &resName,
+ void load(MSurface &backSurface, DepthSurface &depthSurface, const Common::String &resName,
int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo);
/**
@@ -223,6 +228,8 @@ public:
int roomNumber() const { return _header._roomNumber; }
void resetSpriteSetsCount() { _header._spriteSetsCount = 0; } // CHECKME: See if it doesn't leak the memory when the destructor is called
+
+ SpriteAsset *getSpriteSet(int idx) { return _spriteSets[idx]; }
};
} // End of namespace MADS
diff --git a/engines/mads/audio.cpp b/engines/mads/audio.cpp
index 1c61e13957..def2cd6c62 100644
--- a/engines/mads/audio.cpp
+++ b/engines/mads/audio.cpp
@@ -37,6 +37,7 @@ AudioPlayer::AudioPlayer(Audio::Mixer *mixer, uint32 gameID) : _mixer(mixer), _g
AudioPlayer::~AudioPlayer() {
_dsrEntries.clear();
+ _filename = "";
}
bool AudioPlayer::isPlaying() const {
@@ -65,25 +66,27 @@ void AudioPlayer::setDefaultSoundGroup() {
}
void AudioPlayer::setSoundGroup(const Common::String &filename) {
- _dsrEntries.clear();
-
- _filename = filename;
- _dsrFile.open(filename);
-
- // Read header
- uint16 entryCount = _dsrFile.readUint16LE();
-
- for (uint16 i = 0; i < entryCount; i++) {
- DSREntry newEntry;
- newEntry.frequency = _dsrFile.readUint16LE();
- newEntry.channels = _dsrFile.readUint32LE();
- newEntry.compSize = _dsrFile.readUint32LE();
- newEntry.uncompSize = _dsrFile.readUint32LE();
- newEntry.offset = _dsrFile.readUint32LE();
- _dsrEntries.push_back(newEntry);
+ if (_filename != filename) {
+ _dsrEntries.clear();
+
+ _filename = filename;
+ _dsrFile.open(filename);
+
+ // Read header
+ uint16 entryCount = _dsrFile.readUint16LE();
+
+ for (uint16 i = 0; i < entryCount; i++) {
+ DSREntry newEntry;
+ newEntry.frequency = _dsrFile.readUint16LE();
+ newEntry.channels = _dsrFile.readUint32LE();
+ newEntry.compSize = _dsrFile.readUint32LE();
+ newEntry.uncompSize = _dsrFile.readUint32LE();
+ newEntry.offset = _dsrFile.readUint32LE();
+ _dsrEntries.push_back(newEntry);
+ }
+
+ _dsrFile.close();
}
-
- _dsrFile.close();
}
void AudioPlayer::playSound(int soundIndex, bool loop) {
@@ -126,4 +129,8 @@ void AudioPlayer::playSound(int soundIndex, bool loop) {
*/
}
+void AudioPlayer::stop() {
+ _mixer->stopHandle(_handle);
+}
+
} // End of namespace M4
diff --git a/engines/mads/audio.h b/engines/mads/audio.h
index 21f4bed59a..13c540bf85 100644
--- a/engines/mads/audio.h
+++ b/engines/mads/audio.h
@@ -46,6 +46,7 @@ public:
void setSoundGroup(const Common::String &filename);
void setDefaultSoundGroup();
void playSound(int soundIndex, bool loop = false);
+ void stop();
void setVolume(int volume);
bool isPlaying() const;
diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp
index 6bc6cf572d..99251f9fbb 100644
--- a/engines/mads/debugger.cpp
+++ b/engines/mads/debugger.cpp
@@ -24,6 +24,7 @@
#include "mads/compression.h"
#include "mads/mads.h"
#include "mads/debugger.h"
+#include "mads/nebular/menu_nebular.h"
namespace MADS {
@@ -46,6 +47,8 @@ Debugger::Debugger(MADSEngine *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("show_item", WRAP_METHOD(Debugger, Cmd_ShowItem));
registerCmd("dump_items", WRAP_METHOD(Debugger, Cmd_DumpItems));
registerCmd("item", WRAP_METHOD(Debugger, Cmd_Item));
+ registerCmd("play_anim", WRAP_METHOD(Debugger, Cmd_PlayAnim));
+ registerCmd("play_text", WRAP_METHOD(Debugger, Cmd_PlayText));
}
static int strToInt(const char *s) {
@@ -348,4 +351,44 @@ bool Debugger::Cmd_Item(int argc, const char **argv) {
}
}
+bool Debugger::Cmd_PlayAnim(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Usage: %s <anim name>\n", argv[0]);
+ return true;
+ } else {
+ Common::String resName = argv[1];
+ if (resName.hasPrefix("@"))
+ resName.deleteChar(0);
+
+ Common::File f;
+ if (f.exists(resName) || f.exists(resName + ".res")) {
+ AnimationView::execute(_vm, resName);
+ return false;
+ } else {
+ debugPrintf("Could not find resource file\n");
+ return true;
+ }
+ }
+}
+
+bool Debugger::Cmd_PlayText(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Usage: %s <text name>\n", argv[0]);
+ return true;
+ } else {
+ Common::String resName = argv[1];
+ if (resName.hasPrefix("@"))
+ resName.deleteChar(0);
+
+ Common::File f;
+ if (f.exists(resName) || f.exists(resName + ".txr")) {
+ TextView::execute(_vm, resName);
+ return false;
+ } else {
+ debugPrintf("Could not find resource file\n");
+ return true;
+ }
+ }
+}
+
} // End of namespace MADS
diff --git a/engines/mads/debugger.h b/engines/mads/debugger.h
index 351eb13615..c8fee5f5b2 100644
--- a/engines/mads/debugger.h
+++ b/engines/mads/debugger.h
@@ -49,6 +49,8 @@ protected:
bool Cmd_ShowItem(int argc, const char **argv);
bool Cmd_DumpItems(int argc, const char **argv);
bool Cmd_Item(int argc, const char **argv);
+ bool Cmd_PlayAnim(int argc, const char **argv);
+ bool Cmd_PlayText(int argc, const char **argv);
public:
bool _showMousePos;
public:
diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp
index 7e6909d113..5e38f34fc6 100644
--- a/engines/mads/dialogs.cpp
+++ b/engines/mads/dialogs.cpp
@@ -395,4 +395,78 @@ Dialogs::Dialogs(MADSEngine *vm)
_pendingDialog = DIALOG_NONE;
}
+/*------------------------------------------------------------------------*/
+
+FullScreenDialog::FullScreenDialog(MADSEngine *vm) : _vm(vm) {
+ switch (_vm->getGameID()) {
+ case GType_RexNebular:
+ _screenId = 990;
+ break;
+ case GType_Phantom:
+ _screenId = 920;
+ break;
+ case GType_Dragonsphere:
+ _screenId = 922;
+ break;
+ default:
+ error("FullScreenDialog:Unknown game");
+ }
+ _palFlag = true;
+}
+
+FullScreenDialog::~FullScreenDialog() {
+ _vm->_screen.resetClipBounds();
+ _vm->_game->_scene.restrictScene();
+}
+
+void FullScreenDialog::display() {
+ Game &game = *_vm->_game;
+ Scene &scene = game._scene;
+
+ int nextSceneId = scene._nextSceneId;
+ int currentSceneId = scene._currentSceneId;
+ int priorSceneId = scene._priorSceneId;
+
+ if (_screenId > 0) {
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->load(_screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface);
+ }
+
+ scene._priorSceneId = priorSceneId;
+ scene._currentSceneId = currentSceneId;
+ scene._nextSceneId = nextSceneId;
+
+ _vm->_events->initVars();
+ game._kernelMode = KERNEL_ROOM_INIT;
+
+ byte pal[768];
+ if (_vm->_screenFade) {
+ Common::fill(&pal[0], &pal[PALETTE_SIZE], 0);
+ _vm->_palette->setFullPalette(pal);
+ } else {
+ _vm->_palette->getFullPalette(pal);
+ _vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16);
+ }
+
+ // Set Fx state and palette entries
+ game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kCenterVertTransition;
+ game._trigger = 0;
+
+ // Clear the screen and draw the upper and lower horizontal lines
+ _vm->_screen.empty();
+ _vm->_palette->setLowRange();
+ _vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
+ _vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
+ _vm->_screen.resetClipBounds();
+ _vm->_screen.copyRectToScreen(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+
+ // Restrict the screen to the area between the two lines
+ _vm->_screen.setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH,
+ DIALOG_TOP + MADS_SCENE_HEIGHT));
+ _vm->_game->_scene.restrictScene();
+
+ if (_screenId > 0)
+ scene._spriteSlots.fullRefresh();
+}
+
} // End of namespace MADS
diff --git a/engines/mads/dialogs.h b/engines/mads/dialogs.h
index c586a6f1fe..317c7bd792 100644
--- a/engines/mads/dialogs.h
+++ b/engines/mads/dialogs.h
@@ -30,6 +30,8 @@
namespace MADS {
+#define DIALOG_TOP 22
+
class Dialog {
private:
void setDialogPalette();
@@ -226,6 +228,36 @@ public:
virtual bool show(int messageId, int objectId = -1) = 0;
};
+class FullScreenDialog: public EventTarget {
+protected:
+ /**
+ * Engine reference
+ */
+ MADSEngine *_vm;
+
+ /**
+ * Screen/scene to show background from
+ */
+ int _screenId;
+
+ /**
+ * Flag for palette initialization
+ */
+ bool _palFlag;
+
+ /**
+ * Handles displaying the screen background and dialog
+ */
+ virtual void display();
+public:
+ /**
+ * Constructor
+ */
+ FullScreenDialog(MADSEngine *vm);
+
+ virtual ~FullScreenDialog();
+};
+
} // End of namespace MADS
#endif /* MADS_DIALOGS_H */
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index b544eff2db..63a7e40d1b 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -433,8 +433,6 @@ void Game::handleKeypress(const Common::Event &event) {
default:
break;
}
-
- warning("TODO: handleKeypress - %d", (int)event.kbd.keycode);
}
void Game::synchronize(Common::Serializer &s, bool phase1) {
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index 59eec40bcc..52a0b40561 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -68,6 +68,8 @@ MADSEngine::~MADSEngine() {
delete _resources;
delete _sound;
delete _audio;
+
+ _mixer->stopAll();
}
void MADSEngine::initialize() {
@@ -103,9 +105,6 @@ Common::Error MADSEngine::run() {
// Run the game
_game->run();
- // Dummy loop to keep application active
- _events->delay(9999);
-
return Common::kNoError;
}
diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp
new file mode 100644
index 0000000000..03afc70c3e
--- /dev/null
+++ b/engines/mads/menu_views.cpp
@@ -0,0 +1,768 @@
+/* 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 "common/scummsys.h"
+#include "mads/game.h"
+#include "mads/mads.h"
+#include "mads/menu_views.h"
+#include "mads/resources.h"
+#include "mads/scene.h"
+#include "mads/screen.h"
+
+namespace MADS {
+
+MenuView::MenuView(MADSEngine *vm) : FullScreenDialog(vm) {
+ _breakFlag = false;
+ _redrawFlag = true;
+ _palFlag = false;
+}
+
+void MenuView::show() {
+ Scene &scene = _vm->_game->_scene;
+ EventsManager &events = *_vm->_events;
+ _vm->_screenFade = SCREEN_FADE_FAST;
+
+ scene._spriteSlots.reset(true);
+ display();
+
+ events.setEventTarget(this);
+ events.hideCursor();
+
+ while (!_breakFlag && !_vm->shouldQuit()) {
+ if (_redrawFlag) {
+ scene._kernelMessages.update();
+
+ _vm->_game->_scene.drawElements(_vm->_game->_fx, _vm->_game->_fx);
+ _redrawFlag = false;
+ }
+
+ _vm->_events->waitForNextFrame();
+ _vm->_game->_fx = kTransitionNone;
+ doFrame();
+ }
+
+ events.setEventTarget(nullptr);
+ _vm->_sound->stop();
+}
+
+void MenuView::display() {
+ _vm->_palette->resetGamePalette(4, 8);
+
+ FullScreenDialog::display();
+}
+
+bool MenuView::onEvent(Common::Event &event) {
+ if (event.type == Common::EVENT_KEYDOWN || event.type == Common::EVENT_LBUTTONDOWN) {
+ _breakFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+ return true;
+ }
+
+ return false;
+}
+
+Common::String MenuView::getResourceName() {
+ Common::String s(_filename);
+ s.toLowercase();
+ while (s.contains('.'))
+ s.deleteLastChar();
+
+ return s;
+}
+
+/*------------------------------------------------------------------------*/
+
+char TextView::_resourceName[100];
+#define TEXTVIEW_LINE_SPACING 2
+#define TEXT_ANIMATION_DELAY 100
+#define TV_NUM_FADE_STEPS 40
+#define TV_FADE_DELAY_MILLI 50
+
+void TextView::execute(MADSEngine *vm, const Common::String &resName) {
+ assert(resName.size() < 100);
+ Common::strlcpy(_resourceName, resName.c_str(), sizeof(_resourceName));
+ vm->_dialogs->_pendingDialog = DIALOG_TEXTVIEW;
+}
+
+TextView::TextView(MADSEngine *vm) : MenuView(vm) {
+ _animating = false;
+ _panSpeed = 0;
+ _spareScreen = nullptr;
+ _scrollCount = 0;
+ _lineY = -1;
+ _scrollTimeout = 0;
+ _panCountdown = 0;
+ _translationX = 0;
+ _screenId = -1;
+
+ _font = _vm->_font->getFont(FONT_CONVERSATION);
+ _vm->_palette->resetGamePalette(4, 0);
+
+ load();
+}
+
+TextView::~TextView() {
+ // Turn off palette cycling as well as any playing sound
+ Scene &scene = _vm->_game->_scene;
+ scene._cyclingActive = false;
+ _vm->_sound->stop();
+}
+
+void TextView::load() {
+ Common::String scriptName(_resourceName);
+ scriptName += ".txr";
+
+ _filename = scriptName;
+ if (!_script.open(scriptName))
+ error("Could not open resource %s", _resourceName);
+
+ processLines();
+}
+
+void TextView::processLines() {
+ if (_script.eos())
+ error("Attempted to read past end of response file");
+
+ while (!_script.eos()) {
+ // Read in the next line
+ _script.readLine(_currentLine, 79);
+ char *p = _currentLine + strlen(_currentLine) - 1;
+ if (*p == '\n')
+ *p = '\0';
+
+ // Commented out line, so go loop for another
+ if (_currentLine[0] == '#')
+ continue;
+
+ // Process the line
+ char *cStart = strchr(_currentLine, '[');
+ if (cStart) {
+ while (cStart) {
+ // Loop for possible multiple commands on one line
+ char *cEnd = strchr(_currentLine, ']');
+ if (!cEnd)
+ error("Unterminated command '%s' in response file", _currentLine);
+
+ *cEnd = '\0';
+ processCommand();
+
+ // Copy rest of line (if any) to start of buffer
+ Common::strlcpy(_currentLine, cEnd + 1, sizeof(_currentLine));
+
+ cStart = strchr(_currentLine, '[');
+ }
+
+ if (_currentLine[0]) {
+ processText();
+ break;
+ }
+
+ } else {
+ processText();
+ break;
+ }
+ }
+}
+
+void TextView::processCommand() {
+ Scene &scene = _vm->_game->_scene;
+ Common::String scriptLine(_currentLine + 1);
+ scriptLine.toUppercase();
+ const char *paramP;
+ const char *commandStr = scriptLine.c_str();
+
+ if (!strncmp(commandStr, "BACKGROUND", 10)) {
+ // Set the background
+ paramP = commandStr + 10;
+ resetPalette();
+ int screenId = getParameter(&paramP);
+
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->load(screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface);
+ scene._spriteSlots.fullRefresh();
+ _redrawFlag = true;
+
+ } else if (!strncmp(commandStr, "GO", 2)) {
+ _animating = true;
+
+ } else if (!strncmp(commandStr, "PAN", 3)) {
+ // Set panning values
+ paramP = commandStr + 3;
+ int panX = getParameter(&paramP);
+ int panY = getParameter(&paramP);
+ int panSpeed = getParameter(&paramP);
+
+ if ((panX != 0) || (panY != 0)) {
+ _pan = Common::Point(panX, panY);
+ _panSpeed = panSpeed;
+ }
+
+ } else if (!strncmp(commandStr, "DRIVER", 6)) {
+ // Set the driver to use
+ paramP = commandStr + 7;
+
+ if (!strncmp(paramP, "#SOUND.00", 9)) {
+ int driverNum = paramP[9] - '0';
+ _vm->_sound->init(driverNum);
+ }
+ } else if (!strncmp(commandStr, "SOUND", 5)) {
+ // Set sound number
+ paramP = commandStr + 5;
+ int soundId = getParameter(&paramP);
+ _vm->_sound->command(soundId);
+
+ } else if (!strncmp(commandStr, "COLOR", 5) && ((commandStr[5] == '0') ||
+ (commandStr[5] == '1'))) {
+ // Set the text colors
+ int index = commandStr[5] - '0';
+ paramP = commandStr + 6;
+
+ byte r = getParameter(&paramP);
+ byte g = getParameter(&paramP);
+ byte b = getParameter(&paramP);
+
+ _vm->_palette->setEntry(5 + index, r, g, b);
+
+ } else if (!strncmp(commandStr, "SPARE", 5)) {
+ // Sets a secondary background number that can be later switched in with a PAGE command
+ paramP = commandStr + 6;
+ int spareIndex = commandStr[5] - '0';
+ assert(spareIndex < 4);
+ int screenId = getParameter(&paramP);
+
+ // Load the spare background
+ SceneInfo *sceneInfo = SceneInfo::init(_vm);
+ sceneInfo->_width = MADS_SCREEN_WIDTH;
+ sceneInfo->_height = MADS_SCENE_HEIGHT;
+ _spareScreens[spareIndex].setSize(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ sceneInfo->loadMadsV1Background(screenId, "", SCENEFLAG_TRANSLATE,
+ _spareScreens[spareIndex]);
+ delete sceneInfo;
+
+ } else if (!strncmp(commandStr, "PAGE", 4)) {
+ // Signals to change to a previous specified secondary background
+ paramP = commandStr + 4;
+ int spareIndex = getParameter(&paramP);
+
+ // Only allow background switches if one isn't currently in progress
+ if (!_spareScreen && _spareScreens[spareIndex].getPixels() != nullptr) {
+ _spareScreen = &_spareScreens[spareIndex];
+ _translationX = 0;
+ }
+
+ } else {
+ error("Unknown response command: '%s'", commandStr);
+ }
+}
+
+int TextView::getParameter(const char **paramP) {
+ if ((**paramP != '=') && (**paramP != ','))
+ return 0;
+
+ int result = 0;
+ ++*paramP;
+ while ((**paramP >= '0') && (**paramP <= '9')) {
+ result = result * 10 + (**paramP - '0');
+ ++*paramP;
+ }
+
+ return result;
+}
+
+void TextView::processText() {
+ int xStart;
+
+ if (!strcmp(_currentLine, "***")) {
+ // Special signifier for end of script
+ _scrollCount = _font->getHeight() * 13;
+ _lineY = -1;
+ return;
+ }
+
+ _lineY = 0;
+
+ // Lines are always centered, except if line contains a '@', in which case the
+ // '@' marks the position that must be horizontally centered
+ char *centerP = strchr(_currentLine, '@');
+ if (centerP) {
+ *centerP = '\0';
+ xStart = (MADS_SCREEN_WIDTH / 2) - _font->getWidth(_currentLine);
+
+ // Delete the @ character and shift back the remainder of the string
+ char *p = centerP + 1;
+ if (*p == ' ') ++p;
+ strcpy(centerP, p);
+
+ } else {
+ int lineWidth = _font->getWidth(_currentLine);
+ xStart = (MADS_SCREEN_WIDTH - lineWidth) / 2;
+ }
+
+ // Add the new line to the list of pending lines
+ TextLine tl;
+ tl._pos = Common::Point(xStart, MADS_SCENE_HEIGHT);
+ tl._line = _currentLine;
+ tl._textDisplayIndex = -1;
+ _textLines.push_back(tl);
+}
+
+void TextView::display() {
+ FullScreenDialog::display();
+}
+
+void TextView::resetPalette() {
+ _vm->_palette->resetGamePalette(8, 8);
+ _vm->_palette->setEntry(5, 0, 63, 63);
+ _vm->_palette->setEntry(6, 0, 45, 45);
+}
+
+void TextView::doFrame() {
+ Scene &scene = _vm->_game->_scene;
+ if (!_animating)
+ return;
+
+ // Only update state if wait period has expired
+ uint32 currTime = g_system->getMillis();
+
+ // If a screen transition is in progress and it's time for another column, handle it
+ if (_spareScreen) {
+ byte *srcP = _spareScreen->getBasePtr(_translationX, 0);
+ byte *bgP = scene._backgroundSurface.getBasePtr(_translationX, 0);
+ byte *screenP = (byte *)_vm->_screen.getBasePtr(_translationX, 0);
+
+ for (int y = 0; y < MADS_SCENE_HEIGHT; ++y, srcP += MADS_SCREEN_WIDTH,
+ bgP += MADS_SCREEN_WIDTH, screenP += MADS_SCREEN_WIDTH) {
+ *bgP = *srcP;
+ *screenP = *srcP;
+ }
+
+ // Flag the column of the screen is modified
+ _vm->_screen.copyRectToScreen(Common::Rect(_translationX, 0,
+ _translationX + 1, MADS_SCENE_HEIGHT));
+
+ // Keep moving the column to copy to the right
+ if (++_translationX == MADS_SCREEN_WIDTH) {
+ // Surface transition is complete
+ _spareScreen = nullptr;
+ }
+ }
+
+ // Make sure it's time for an update
+ if (currTime < _scrollTimeout)
+ return;
+ _scrollTimeout = g_system->getMillis() + TEXT_ANIMATION_DELAY;
+ _redrawFlag = true;
+
+ // If any panning values are set, pan the background surface
+ if ((_pan.x != 0) || (_pan.y != 0)) {
+ if (_panCountdown > 0) {
+ --_panCountdown;
+ return;
+ }
+
+ // Handle horizontal panning
+ if (_pan.x != 0) {
+ byte *lineTemp = new byte[_pan.x];
+ for (int y = 0; y < MADS_SCENE_HEIGHT; ++y) {
+ byte *pixelsP = (byte *)scene._backgroundSurface.getBasePtr(0, y);
+
+ // Copy the first X pixels into temp buffer, move the rest of the line
+ // to the start of the line, and then move temp buffer pixels to end of line
+ Common::copy(pixelsP, pixelsP + _pan.x, lineTemp);
+ Common::copy(pixelsP + _pan.x, pixelsP + MADS_SCREEN_WIDTH, pixelsP);
+ Common::copy(lineTemp, lineTemp + _pan.x, pixelsP + MADS_SCREEN_WIDTH - _pan.x);
+ }
+
+ delete[] lineTemp;
+ }
+
+ // Handle vertical panning
+ if (_pan.y != 0) {
+ // Store the bottom Y lines into a temp buffer, move the rest of the lines down,
+ // and then copy the stored lines back to the top of the screen
+ byte *linesTemp = new byte[_pan.y * MADS_SCREEN_WIDTH];
+ byte *pixelsP = (byte *)scene._backgroundSurface.getBasePtr(0, MADS_SCENE_HEIGHT - _pan.y);
+ Common::copy(pixelsP, pixelsP + MADS_SCREEN_WIDTH * _pan.y, linesTemp);
+
+ for (int y = MADS_SCENE_HEIGHT - 1; y >= _pan.y; --y) {
+ byte *destP = (byte *)scene._backgroundSurface.getBasePtr(0, y);
+ byte *srcP = (byte *)scene._backgroundSurface.getBasePtr(0, y - _pan.y);
+ Common::copy(srcP, srcP + MADS_SCREEN_WIDTH, destP);
+ }
+
+ Common::copy(linesTemp, linesTemp + _pan.y * MADS_SCREEN_WIDTH,
+ (byte *)scene._backgroundSurface.getPixels());
+ delete[] linesTemp;
+ }
+
+ // Flag for a full screen refresh
+ scene._spriteSlots.fullRefresh();
+ }
+
+ // Scroll all active text lines up
+ for (int i = _textLines.size() - 1; i >= 0; --i) {
+ TextLine &tl = _textLines[i];
+ if (tl._textDisplayIndex != -1)
+ // Expire the text line that's already on-screen
+ scene._textDisplay.expire(tl._textDisplayIndex);
+
+ tl._pos.y--;
+ if (tl._pos.y < 0) {
+ _textLines.remove_at(i);
+ } else {
+ tl._textDisplayIndex = scene._textDisplay.add(tl._pos.x, tl._pos.y,
+ 0x605, -1, tl._line, _font);
+ }
+ }
+
+ if (_scrollCount > 0) {
+ // Handling final scrolling of text off of screen
+ if (--_scrollCount == 0) {
+ scriptDone();
+ return;
+ }
+ } else {
+ // Handling a text row
+ if (++_lineY == (_font->getHeight() + TEXTVIEW_LINE_SPACING))
+ processLines();
+ }
+}
+
+void TextView::scriptDone() {
+ _breakFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+}
+
+/*------------------------------------------------------------------------*/
+
+char AnimationView::_resourceName[100];
+
+void AnimationView::execute(MADSEngine *vm, const Common::String &resName) {
+ assert(resName.size() < 100);
+ Common::strlcpy(_resourceName, resName.c_str(), sizeof(_resourceName));
+ vm->_dialogs->_pendingDialog = DIALOG_ANIMVIEW;
+}
+
+AnimationView::AnimationView(MADSEngine *vm) : MenuView(vm) {
+ _redrawFlag = false;
+
+ _soundDriverLoaded = false;
+ _previousUpdate = 0;
+ _screenId = -1;
+ _resetPalette = false;
+ _resyncMode = NEVER;
+ _v1 = 0;
+ _v2 = -1;
+ _resourceIndex = -1;
+ _currentAnimation = nullptr;
+ _sfx = 0;
+ _soundFlag = _bgLoadFlag = true;
+ _showWhiteBars = true;
+ _manualFrameNumber = 0;
+ _manualSpriteSet = nullptr;
+ _manualStartFrame = _manualEndFrame = 0;
+ _manualFrame2 = 0;
+ _animFrameNumber = 0;
+ _nextCyclingActive = false;
+ _sceneInfo = SceneInfo::init(_vm);
+
+ load();
+}
+
+AnimationView::~AnimationView() {
+ // Turn off palette cycling as well as any playing sound
+ Scene &scene = _vm->_game->_scene;
+ scene._cyclingActive = false;
+ _vm->_sound->stop();
+ _vm->_audio->stop();
+
+ // Delete data
+ delete _currentAnimation;
+ delete _sceneInfo;
+}
+
+void AnimationView::load() {
+ Common::String resName(_resourceName);
+ if (!resName.hasSuffix("."))
+ resName += ".res";
+
+ _filename = resName;
+ if (!_script.open(resName))
+ error("Could not open resource %s", resName.c_str());
+
+ processLines();
+}
+
+void AnimationView::display() {
+ Scene &scene = _vm->_game->_scene;
+ _vm->_palette->initPalette();
+ Common::fill(&_vm->_palette->_cyclingPalette[0], &_vm->_palette->_cyclingPalette[PALETTE_SIZE], 0);
+
+ _vm->_palette->resetGamePalette(1, 8);
+ scene._spriteSlots.reset();
+ scene._paletteCycles.clear();
+
+ MenuView::display();
+}
+
+bool AnimationView::onEvent(Common::Event &event) {
+ // Wait for the Escape key or a mouse press
+ if (((event.type == Common::EVENT_KEYDOWN) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) ||
+ (event.type == Common::EVENT_LBUTTONUP)) {
+ scriptDone();
+ return true;
+ }
+
+ return false;
+}
+
+void AnimationView::doFrame() {
+ Scene &scene = _vm->_game->_scene;
+
+ if (_resourceIndex == -1 || _currentAnimation->freeFlag()) {
+ if (++_resourceIndex == (int)_resources.size()) {
+ scriptDone();
+ } else {
+ scene._frameStartTime = 0;
+ loadNextResource();
+ }
+ } else if (_currentAnimation->getCurrentFrame() == 1) {
+ scene._cyclingActive = _nextCyclingActive;
+ }
+
+ if (_currentAnimation) {
+ ++scene._frameStartTime;
+ _currentAnimation->update();
+ _redrawFlag = true;
+ }
+}
+
+void AnimationView::loadNextResource() {
+ Scene &scene = _vm->_game->_scene;
+ Palette &palette = *_vm->_palette;
+ ResourceEntry &resEntry = _resources[_resourceIndex];
+ Common::Array<PaletteCycle> paletteCycles;
+
+ if (resEntry._bgFlag)
+ palette.resetGamePalette(1, 8);
+
+ palette._mainPalette[253 * 3] = palette._mainPalette[253 * 3 + 1]
+ = palette._mainPalette[253 * 3 + 2] = 0xb4;
+ palette.setPalette(&palette._mainPalette[253 * 3], 253, 1);
+
+ // Free any previous messages
+ scene._kernelMessages.reset();
+
+ // Handle the bars at the top/bottom
+ if (resEntry._showWhiteBars) {
+ // For animations the screen has been clipped to the middle 156 rows.
+ // So although it's slightly messy, bypass our screen class entirely,
+ // and draw the horizontal lines directly on the physiacl screen surface
+ Graphics::Surface *s = g_system->lockScreen();
+ s->hLine(0, 20, MADS_SCREEN_WIDTH, 253);
+ s->hLine(0, 179, MADS_SCREEN_WIDTH, 253);
+ g_system->unlockScreen();
+ }
+
+ // Load the new animation
+ delete _currentAnimation;
+ _currentAnimation = Animation::init(_vm, &scene);
+ int flags = ANIMFLAG_ANIMVIEW | (resEntry._bgFlag ? ANIMFLAG_LOAD_BACKGROUND : 0);
+ _currentAnimation->load(scene._backgroundSurface, scene._depthSurface,
+ resEntry._resourceName, flags, &paletteCycles, _sceneInfo);
+
+ // Signal for a screen refresh
+ scene._spriteSlots.fullRefresh();
+
+ // If a sound driver has been specified, then load the correct one
+ if (!_currentAnimation->_header._soundName.empty()) {
+ const char *chP = strchr(_currentAnimation->_header._soundName.c_str(), '.');
+ assert(chP);
+
+ // Handle both Rex naming (xxx.009) and naming in later games (e.g. xxx.ph9)
+ int driverNum = atoi(chP + 3);
+ // HACK for Dragon
+ if (_currentAnimation->_header._soundName == "#SOUND.DRG")
+ driverNum = 9;
+ _vm->_sound->init(driverNum);
+ }
+
+ // Handle any manual setup
+ if (_currentAnimation->_header._manualFlag) {
+ _manualFrameNumber = _currentAnimation->_header._spritesIndex;
+ _manualSpriteSet = _currentAnimation->getSpriteSet(_manualFrameNumber);
+ }
+
+ // Set the sound data for the animation
+ _vm->_sound->setEnabled(resEntry._soundFlag);
+
+ Common::String dsrName = _currentAnimation->_header._dsrName;
+ if (!dsrName.empty())
+ _vm->_audio->setSoundGroup(dsrName);
+
+ // Start the new animation
+ _currentAnimation->startAnimation(0);
+
+ // Handle the palette and cycling palette
+ scene._cyclingActive = false;
+ Common::copy(&palette._mainPalette[0], &palette._mainPalette[PALETTE_SIZE],
+ &palette._cyclingPalette[0]);
+
+ _vm->_game->_fx = (ScreenTransition)resEntry._fx;
+ _nextCyclingActive = paletteCycles.size() > 0;
+ if (!_vm->_game->_fx) {
+ palette.setFullPalette(palette._mainPalette);
+ }
+
+ scene.initPaletteAnimation(paletteCycles, _nextCyclingActive && !_vm->_game->_fx);
+}
+
+void AnimationView::scriptDone() {
+ _breakFlag = true;
+ _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
+}
+
+void AnimationView::processLines() {
+ if (_script.eos()) {
+ // end of script, end animation
+ scriptDone();
+ return;
+ }
+
+ while (!_script.eos()) {
+ // Get in next line
+ _currentLine.clear();
+ char c;
+ while (!_script.eos() && (c = _script.readByte()) != '\n') {
+ if (c != '\r' && c != '\0')
+ _currentLine += c;
+ }
+
+ // Process the line
+ while (!_currentLine.empty()) {
+ if (_currentLine.hasPrefix("-")) {
+ _currentLine.deleteChar(0);
+
+ processCommand();
+ } else {
+ // Get resource name
+ Common::String resName;
+ while (!_currentLine.empty() && (c = _currentLine[0]) != ' ') {
+ _currentLine.deleteChar(0);
+ resName += c;
+ }
+
+ // Add resource into list along with any set state information
+ _resources.push_back(ResourceEntry(resName, _sfx, _soundFlag,
+ _bgLoadFlag, _showWhiteBars));
+
+ // Fx resets between resource entries
+ _sfx = 0;
+ }
+
+ // Skip any spaces
+ while (_currentLine.hasPrefix(" "))
+ _currentLine.deleteChar(0);
+ }
+ }
+}
+
+void AnimationView::processCommand() {
+ // Get the command character
+ char commandChar = toupper(_currentLine[0]);
+ _currentLine.deleteChar(0);
+
+ // Handle the command
+ switch (commandChar) {
+ case 'B':
+ _soundFlag = !_soundFlag;
+ break;
+ case 'H':
+ // -h[:ex] Disable EMS / XMS high memory support
+ if (_currentLine.hasPrefix(":"))
+ _currentLine.deleteChar(0);
+ while (_currentLine.hasPrefix("e") || _currentLine.hasPrefix("x"))
+ _currentLine.deleteChar(0);
+ break;
+ case 'O':
+ // -o:xxx Specify opening special effect
+ assert(_currentLine[0] == ':');
+ _currentLine.deleteChar(0);
+ _sfx = getParameter();
+ break;
+ case 'P':
+ // Switch to CONCAT mode, which is ignored anyway
+ break;
+ case 'R': {
+ // Resynch timer (always, beginning, never)
+ assert(_currentLine[0] == ':');
+ _currentLine.deleteChar(0);
+
+ char v = toupper(_currentLine[0]);
+ _currentLine.deleteChar(0);
+ if (v == 'N')
+ _resyncMode = NEVER;
+ else if (v == 'A')
+ _resyncMode = ALWAYS;
+ else if (v == 'B')
+ _resyncMode = BEGINNING;
+ else
+ error("Unknown parameter");
+ break;
+ }
+ case 'W':
+ // Switch white bars being visible
+ _showWhiteBars = !_showWhiteBars;
+ break;
+ case 'X':
+ // Exit after animation finishes. Ignore
+ break;
+ case 'D':
+ // Unimplemented and ignored in the original. Ignore as well
+ break;
+ case 'Y':
+ // Reset palette on startup
+ _resetPalette = true;
+ break;
+ default:
+ error("Unknown command char: '%c'", commandChar);
+ }
+}
+
+int AnimationView::getParameter() {
+ int result = 0;
+
+ while (!_currentLine.empty()) {
+ char c = _currentLine[0];
+
+ if (c >= '0' && c <= '9') {
+ _currentLine.deleteChar(0);
+ result = result * 10 + (c - '0');
+ } else {
+ break;
+ }
+ }
+
+ return result;
+}
+
+} // End of namespace MADS
diff --git a/engines/mads/menu_views.h b/engines/mads/menu_views.h
new file mode 100644
index 0000000000..cc5a13006f
--- /dev/null
+++ b/engines/mads/menu_views.h
@@ -0,0 +1,225 @@
+/* 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.
+ *
+ */
+
+#ifndef MADS_MENU_VIEWS_H
+#define MADS_MENU_VIEWS_H
+
+#include "common/scummsys.h"
+#include "mads/dialogs.h"
+#include "mads/game.h"
+#include "mads/msurface.h"
+
+namespace MADS {
+
+class MADSEngine;
+
+class MenuView: public FullScreenDialog {
+protected:
+ bool _breakFlag;
+ bool _redrawFlag;
+ Common::String _filename;
+
+ virtual void doFrame() = 0;
+
+ virtual void display();
+
+ /**
+ * Event handler
+ */
+ virtual bool onEvent(Common::Event &event);
+public:
+ MenuView(MADSEngine *vm);
+
+ virtual ~MenuView() {}
+
+ virtual void show();
+
+ Common::String getResourceName();
+};
+
+struct TextLine {
+ Common::Point _pos;
+ Common::String _line;
+ int _textDisplayIndex;
+};
+
+/**
+ * Scrolling text view
+ */
+class TextView : public MenuView {
+private:
+ static char _resourceName[100];
+
+ bool _animating;
+ Common::Array<TextLine> _textLines;
+ Common::Point _pan;
+ int _panSpeed;
+ MSurface _spareScreens[4];
+ int _scrollCount;
+ int _lineY;
+ uint32 _scrollTimeout;
+ int _panCountdown;
+ int _translationX;
+ Common::File _script;
+ char _currentLine[80];
+ MSurface *_spareScreen;
+ Font *_font;
+private:
+ /**
+ * Load the text resource
+ */
+ void load();
+
+ /**
+ * Process the lines
+ */
+ void processLines();
+
+ /**
+ * Process a command from the script file
+ */
+ void processCommand();
+
+ /**
+ * Process text from the script file
+ */
+ void processText();
+
+ /**
+ * Get a parameter from line
+ */
+ int getParameter(const char **paramP);
+
+ /**
+ * Reset the game palette
+ */
+ void resetPalette();
+protected:
+ virtual void display();
+
+ virtual void doFrame();
+
+ /**
+ * Called when the script is finished
+ */
+ virtual void scriptDone();
+public:
+ /**
+ * Queue the given text resource for display
+ */
+ static void execute(MADSEngine *vm, const Common::String &resName);
+
+ TextView(MADSEngine *vm);
+
+ virtual ~TextView();
+};
+
+enum ResyncMode { NEVER, ALWAYS, BEGINNING };
+
+struct ResourceEntry {
+ Common::String _resourceName;
+ int _fx;
+ bool _soundFlag;
+ bool _bgFlag;
+ bool _showWhiteBars;
+
+ ResourceEntry() {}
+ ResourceEntry(const Common::String &resName, int fx, bool soundFlag,
+ bool bgFlag, bool showWhiteBars) {
+ _resourceName = resName;
+ _fx = fx;
+ _soundFlag = soundFlag;
+ _bgFlag = bgFlag;
+ _showWhiteBars = showWhiteBars;
+ }
+};
+
+struct ResIndexEntry {
+ int _id;
+ int _v;
+ Common::String _resourceName;
+
+ ResIndexEntry() {}
+};
+
+/**
+* Animation cutscene view
+*/
+class AnimationView : public MenuView {
+private:
+ static char _resourceName[100];
+
+ Common::File _script;
+ uint32 _previousUpdate;
+ Common::String _currentLine;
+ bool _soundDriverLoaded;
+ bool _resetPalette;
+ ResyncMode _resyncMode;
+ int _sfx;
+ bool _soundFlag;
+ bool _bgLoadFlag;
+ bool _showWhiteBars;
+ Common::Array<ResourceEntry> _resources;
+ Common::Array<ResIndexEntry> _resIndex;
+ int _v1;
+ int _v2;
+ int _resourceIndex;
+ SceneInfo *_sceneInfo;
+ Animation *_currentAnimation;
+ int _manualFrameNumber;
+ SpriteAsset *_manualSpriteSet;
+ int _manualStartFrame, _manualEndFrame;
+ int _manualFrame2;
+ int _animFrameNumber;
+ bool _nextCyclingActive;
+private:
+ void load();
+
+ void processLines();
+
+ void processCommand();
+
+ int getParameter();
+
+ void loadNextResource();
+protected:
+ virtual void display();
+
+ virtual void doFrame();
+
+ virtual bool onEvent(Common::Event &event);
+
+ virtual void scriptDone();
+public:
+ /**
+ * Queue the given text resource for display
+ */
+ static void execute(MADSEngine *vm, const Common::String &resName);
+
+ AnimationView(MADSEngine *vm);
+
+ virtual ~AnimationView();
+};
+
+} // End of namespace MADS
+
+#endif /* MADS_MENU_VIEWS_H */
diff --git a/engines/mads/module.mk b/engines/mads/module.mk
index 96353e9ae5..fc04a2f8ba 100644
--- a/engines/mads/module.mk
+++ b/engines/mads/module.mk
@@ -35,6 +35,7 @@ MODULE_OBJS := \
hotspots.o \
inventory.o \
mads.o \
+ menu_views.o \
messages.o \
msurface.o \
palette.o \
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index 349f4a5f23..39824bac4b 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -87,7 +87,6 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
// rectangle is always 0, 0
assert(clipRect.top == 0 && clipRect.left == 0);
- // TODO: Put err* and scaled* into SpriteInfo
int errX = info.hotX * info.scaleX % 100;
int errY = info.hotY * info.scaleY % 100;
int scaledWidth = scaleValue(info.width, info.scaleX, errX);
@@ -160,7 +159,6 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
if (status == kStatusDraw && clipY == 0) {
// Draw previously scaled line
- // TODO Implement different drawing types (depth, shadow etc.)
byte *tempDst = dst;
for (int lineX = 0; lineX < scaledWidth; lineX++) {
byte pixel = scaledLineBuf[lineX];
@@ -186,8 +184,6 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
}
dst += pitch;
heightAmt--;
- // TODO depth etc.
- //depthAddress += Destination -> Width;
errY += 100;
if (errY >= 0)
@@ -266,11 +262,11 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
int highestDim = MAX(frameWidth, frameHeight);
bool lineDist[MADS_SCREEN_WIDTH];
- int distIndex = 0;
int distXCount = 0, distYCount = 0;
if (scale != -1) {
int distCtr = 0;
+ int distIndex = 0;
do {
distCtr += scale;
if (distCtr < 100) {
@@ -356,9 +352,10 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
if (widthAmount > 0)
spriteWidth -= widthAmount;
- int spriteRight = spriteLeft + spriteWidth;
if (spriteWidth <= 0)
return;
+
+ int spriteRight = spriteLeft + spriteWidth;
if (flipped) {
destX += distXCount - 1;
spriteLeft = -(distXCount - spriteRight);
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index 3a5bf22eed..ebfb1f437a 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -64,6 +64,11 @@ public:
* Helper method for calculating new dimensions when scaling a sprite
*/
static int scaleValue(int value, int scale, int err);
+
+ /**
+ * Base method for descendents to load their contents
+ */
+ virtual void load(const Common::String &resName) {}
public:
/**
* Basic constructor
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
index 57edbf9c19..f51d046951 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -314,13 +314,13 @@ void DialogsNebular::showDialog() {
break;
}
case DIALOG_TEXTVIEW: {
- TextView *dlg = new TextView(_vm);
+ TextView *dlg = new RexTextView(_vm);
dlg->show();
delete dlg;
break;
}
case DIALOG_ANIMVIEW: {
- AnimationView *dlg = new AnimationView(_vm);
+ AnimationView *dlg = new RexAnimationView(_vm);
dlg->show();
delete dlg;
break;
@@ -553,62 +553,6 @@ void PictureDialog::restore() {
/*------------------------------------------------------------------------*/
-FullScreenDialog::FullScreenDialog(MADSEngine *vm) : _vm(vm) {
- _screenId = 990;
- _palFlag = true;
-}
-
-FullScreenDialog::~FullScreenDialog() {
- _vm->_screen.resetClipBounds();
- _vm->_game->_scene.restrictScene();
-}
-
-void FullScreenDialog::display() {
- Game &game = *_vm->_game;
- Scene &scene = game._scene;
-
- int nextSceneId = scene._nextSceneId;
- int currentSceneId = scene._currentSceneId;
- int priorSceneId = scene._priorSceneId;
-
- SceneInfo *sceneInfo = SceneInfo::init(_vm);
- sceneInfo->load(_screenId, 0, "", 0, scene._depthSurface, scene._backgroundSurface);
-
- scene._priorSceneId = priorSceneId;
- scene._currentSceneId = currentSceneId;
- scene._nextSceneId = nextSceneId;
-
- _vm->_events->initVars();
- game._kernelMode = KERNEL_ROOM_INIT;
-
- byte pal[768];
- if (_vm->_screenFade) {
- Common::fill(&pal[0], &pal[PALETTE_SIZE], 0);
- _vm->_palette->setFullPalette(pal);
- } else {
- _vm->_palette->getFullPalette(pal);
- _vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16);
- }
-
- // Set Fx state and palette entries
- game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kCenterVertTransition;
- game._trigger = 0;
-
- // Clear the screen and draw the upper and lower horizontal lines
- _vm->_screen.empty();
- _vm->_palette->setLowRange();
- _vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
- _vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
- _vm->_screen.copyRectToScreen(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
-
- // Restrict the screen to the area between the two lines
- _vm->_screen.setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH,
- DIALOG_TOP + MADS_SCENE_HEIGHT));
- _vm->_game->_scene.restrictScene();
-}
-
-/*------------------------------------------------------------------------*/
-
GameDialog::DialogLine::DialogLine() {
_active = true;
_state = DLGSTATE_UNSELECTED;
@@ -650,6 +594,9 @@ GameDialog::GameDialog(MADSEngine *vm) : FullScreenDialog(vm) {
_vm->_events->waitCursor();
scene.clearVocab();
scene._dynamicHotspots.clear();
+ // Clear scene sprites and objects
+ scene._spriteSlots.reset();
+ _vm->_game->_screenObjects.clear();
_vm->_dialogs->_defaultPosition = Common::Point(-1, -1);
_menuSpritesIndex = 0;
}
@@ -657,6 +604,14 @@ GameDialog::GameDialog(MADSEngine *vm) : FullScreenDialog(vm) {
void GameDialog::display() {
FullScreenDialog::display();
+ Palette &palette = *_vm->_palette;
+ palette.setEntry(10, 0, 63, 0);
+ palette.setEntry(11, 0, 45, 0);
+ palette.setEntry(12, 63, 63, 0);
+ palette.setEntry(13, 45, 45, 0);
+ palette.setEntry(14, 63, 63, 63);
+ palette.setEntry(15, 45, 45, 45);
+
Scene &scene = _vm->_game->_scene;
SpriteAsset *menuSprites = new SpriteAsset(_vm, "*MENU", 0);
_menuSpritesIndex = scene._sprites.add(menuSprites);
@@ -964,6 +919,7 @@ void GameDialog::refreshText() {
DifficultyDialog::DifficultyDialog(MADSEngine *vm) : GameDialog(vm) {
setLines();
+ _vm->_palette->resetGamePalette(18, 10);
}
void DifficultyDialog::setLines() {
@@ -1108,6 +1064,14 @@ void OptionsDialog::display() {
void OptionsDialog::show() {
Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game;
+
+ // Previous options, restored when cancel is selected
+ bool prevEasyMouse = _vm->_easyMouse;
+ bool prevInvObjectsAnimated = _vm->_invObjectsAnimated;
+ bool prevTextWindowStill = _vm->_textWindowStill;
+ ScreenFade prevScreenFade = _vm->_screenFade;
+ StoryMode prevStoryMode = game._storyMode;
+
do {
_selectedLine = 0;
GameDialog::show();
@@ -1152,10 +1116,15 @@ void OptionsDialog::show() {
switch (_selectedLine) {
case 8: // Done
- // TODO: Copy from temporary config
+ // New options will be applied
break;
case 9: // Cancel
- // TODO: Ignore all changes to temporary config
+ // Revert all options from the saved ones
+ _vm->_easyMouse = prevEasyMouse;
+ _vm->_invObjectsAnimated = prevInvObjectsAnimated;
+ _vm->_textWindowStill = prevTextWindowStill;
+ _vm->_screenFade = prevScreenFade;
+ game._storyMode = prevStoryMode;
break;
default:
break;
diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h
index f64f992611..d00cd87ead 100644
--- a/engines/mads/nebular/dialogs_nebular.h
+++ b/engines/mads/nebular/dialogs_nebular.h
@@ -31,8 +31,6 @@ namespace MADS {
namespace Nebular {
-#define DIALOG_TOP 22
-
enum CapitalizationMode { kUppercase = 0, kLowercase = 1, kUpperAndLower = 2 };
class DialogsNebular : public Dialogs {
@@ -109,36 +107,6 @@ enum DialogTextAlign { ALIGN_NONE = 0, ALIGN_CENTER = -1, ALIGN_AT_CENTER = -2,
enum DialogState { DLGSTATE_UNSELECTED = 0, DLGSTATE_SELECTED = 1, DLGSTATE_FOCUSED = 2 };
-class FullScreenDialog: public EventTarget {
-protected:
- /**
- * Engine reference
- */
- MADSEngine *_vm;
-
- /**
- * Screen/scene to show background from
- */
- int _screenId;
-
- /**
- * Flag for palette initialization
- */
- bool _palFlag;
-
- /**
- * Handles displaying the screen background and dialog
- */
- virtual void display();
-public:
- /**
- * Constructor
- */
- FullScreenDialog(MADSEngine *vm);
-
- virtual ~FullScreenDialog();
-};
-
class GameDialog: public FullScreenDialog {
struct DialogLine {
bool _active;
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
index 902f42507a..eae74d6da0 100644
--- a/engines/mads/nebular/game_nebular.cpp
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -27,6 +27,7 @@
#include "mads/game.h"
#include "mads/screen.h"
#include "mads/msurface.h"
+#include "mads/menu_views.h"
#include "mads/nebular/game_nebular.h"
#include "mads/nebular/dialogs_nebular.h"
#include "mads/nebular/globals_nebular.h"
@@ -309,6 +310,31 @@ void GameNebular::setSectionHandler() {
}
void GameNebular::checkShowDialog() {
+ // Handling to start endgame sequences if the win/lose type has been set
+ switch (_winStatus) {
+ case 1:
+ // No shields failure ending
+ AnimationView::execute(_vm, "rexend1");
+ break;
+ case 2:
+ // Shields, but no targetting failure ending
+ AnimationView::execute(_vm, "rexend2");
+ break;
+ case 3:
+ // Completed game successfully, so activate quotes item on the main menu
+ ConfMan.setBool("ShowQuotes", true);
+ ConfMan.flushToDisk();
+
+ AnimationView::execute(_vm, "rexend3");
+ break;
+ case 4:
+ // Decompression ending
+ TextView::execute(_vm, "ending4");
+ break;
+ }
+ _winStatus = 0;
+
+ // Loop for showing dialogs, if any need to be shown
if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[kCopyProtectFailed]) {
_player.releasePlayerSprites();
diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h
index da607d47ee..efa21a2e73 100644
--- a/engines/mads/nebular/game_nebular.h
+++ b/engines/mads/nebular/game_nebular.h
@@ -133,18 +133,16 @@ public:
virtual void synchronize(Common::Serializer &s, bool phase1);
};
-
+// Section handlers aren't needed in ScummVM implementation
class Section1Handler : public SectionHandler {
public:
Section1Handler(MADSEngine *vm) : SectionHandler(vm) {}
- // TODO: Properly implement handler methods
virtual void preLoadSection() {}
virtual void sectionPtr2() {}
virtual void postLoadSection() {}
};
-// TODO: Properly implement handler classes
typedef Section1Handler Section2Handler;
typedef Section1Handler Section3Handler;
typedef Section1Handler Section4Handler;
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index 88453ecdba..f2f90e2291 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -21,8 +21,10 @@
*/
#include "common/scummsys.h"
+#include "common/config-manager.h"
#include "mads/game.h"
#include "mads/mads.h"
+#include "mads/menu_views.h"
#include "mads/resources.h"
#include "mads/scene.h"
#include "mads/screen.h"
@@ -36,45 +38,6 @@ namespace Nebular {
#define MADS_MENU_Y ((MADS_SCREEN_HEIGHT - MADS_SCENE_HEIGHT) / 2)
#define MADS_MENU_ANIM_DELAY 70
-MenuView::MenuView(MADSEngine *vm) : FullScreenDialog(vm) {
- _breakFlag = false;
- _redrawFlag = true;
- _palFlag = false;
-}
-
-void MenuView::show() {
- Scene &scene = _vm->_game->_scene;
- EventsManager &events = *_vm->_events;
- _vm->_screenFade = SCREEN_FADE_FAST;
-
- scene._spriteSlots.reset(true);
- display();
-
- events.setEventTarget(this);
- events.hideCursor();
-
- while (!_breakFlag && !_vm->shouldQuit()) {
- if (_redrawFlag) {
- _vm->_game->_scene.drawElements(_vm->_game->_fx, _vm->_game->_fx);
- _redrawFlag = false;
- }
-
- _vm->_events->waitForNextFrame();
- _vm->_game->_fx = kTransitionNone;
- doFrame();
- }
-
- events.setEventTarget(nullptr);
-}
-
-void MenuView::display() {
- _vm->_palette->resetGamePalette(4, 8);
-
- FullScreenDialog::display();
-}
-
-/*------------------------------------------------------------------------*/
-
MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
Common::fill(&_menuItems[0], &_menuItems[7], (SpriteAsset *)nullptr);
Common::fill(&_menuItemIndexes[0], &_menuItemIndexes[7], -1);
@@ -91,6 +54,17 @@ MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
}
MainMenu::~MainMenu() {
+ Scene &scene = _vm->_game->_scene;
+ for (int i = 0; i < 7; ++i) {
+ if (_menuItemIndexes[i] != -1)
+ scene._sprites.remove(_menuItemIndexes[i]);
+ }
+
+ scene._spriteSlots.reset();
+}
+
+bool MainMenu::shouldShowQuotes() {
+ return ConfMan.hasKey("ShowQuotes") && ConfMan.getBool("ShowQuotes");
}
void MainMenu::display() {
@@ -132,6 +106,9 @@ void MainMenu::doFrame() {
handleAction((MADSGameAction)_selectedIndex);
} else {
for (_menuItemIndex = 0; _menuItemIndex < 6; ++_menuItemIndex) {
+ if (_menuItemIndex == 4 && !shouldShowQuotes())
+ continue;
+
if (_menuItemIndex != _selectedIndex) {
addSpriteSlot();
}
@@ -151,6 +128,9 @@ void MainMenu::doFrame() {
if (_skipFlag && _menuItemIndex >= 0) {
// Quickly loop through all the menu items to display each's final frame
for (; _menuItemIndex < 6; ++_menuItemIndex) {
+ if (_menuItemIndex == 4 && !shouldShowQuotes())
+ continue;
+
// Draw the final frame of the menuitem
_frameIndex = 0;
addSpriteSlot();
@@ -160,9 +140,12 @@ void MainMenu::doFrame() {
} else {
if ((_menuItemIndex == -1) || (_frameIndex == 0)) {
if (++_menuItemIndex == 6) {
+
// Reached end of display animation
_vm->_events->showCursor();
return;
+ } else if (_menuItemIndex == 4 && !shouldShowQuotes()) {
+ ++_menuItemIndex;
}
_frameIndex = _menuItems[_menuItemIndex]->getCount() - 1;
@@ -340,7 +323,7 @@ void MainMenu::handleAction(MADSGameAction action) {
return;
case SHOW_INTRO:
- AnimationView::execute(_vm, "@rexopen");
+ AnimationView::execute(_vm, "rexopen");
break;
case CREDITS:
@@ -394,6 +377,7 @@ void AdvertView::show() {
events.setEventTarget(nullptr);
_vm->quitGame();
+ events.pollEvents();
}
bool AdvertView::onEvent(Common::Event &event) {
@@ -407,493 +391,16 @@ bool AdvertView::onEvent(Common::Event &event) {
/*------------------------------------------------------------------------*/
-char TextView::_resourceName[100];
-#define TEXTVIEW_LINE_SPACING 2
-#define TEXT_ANIMATION_DELAY 100
-#define TV_NUM_FADE_STEPS 40
-#define TV_FADE_DELAY_MILLI 50
-
-void TextView::execute(MADSEngine *vm, const Common::String &resName) {
- assert(resName.size() < 100);
- strncpy(_resourceName, resName.c_str(), sizeof(_resourceName));
- vm->_dialogs->_pendingDialog = DIALOG_TEXTVIEW;
-}
-
-TextView::TextView(MADSEngine *vm) : MenuView(vm) {
- _animating = false;
- _panSpeed = 0;
- Common::fill(&_spareScreens[0], &_spareScreens[10], 0);
- _spareScreen = nullptr;
- _scrollCount = 0;
- _lineY = -1;
- _scrollTimeout = 0;
- _panCountdown = 0;
- _translationX = 0;
-
- _font = _vm->_font->getFont(FONT_CONVERSATION);
- _vm->_palette->resetGamePalette(4, 0);
- load();
-}
-
-TextView::~TextView() {
- delete _spareScreen;
-}
-
-void TextView::load() {
- Common::String scriptName(_resourceName);
- scriptName += ".txr";
-
- if (!_script.open(scriptName))
- error("Could not open resource %s", _resourceName);
-
- processLines();
-}
-
-void TextView::processLines() {
- if (_script.eos())
- error("Attempted to read past end of response file");
-
- while (!_script.eos()) {
- // Read in the next line
- _script.readLine(_currentLine, 79);
- char *p = _currentLine + strlen(_currentLine) - 1;
- if (*p == '\n')
- *p = '\0';
-
- // Commented out line, so go loop for another
- if (_currentLine[0] == '#')
- continue;
-
- // Process the line
- char *cStart = strchr(_currentLine, '[');
- if (cStart) {
- while (cStart) {
- // Loop for possible multiple commands on one line
- char *cEnd = strchr(_currentLine, ']');
- if (!cEnd)
- error("Unterminated command '%s' in response file", _currentLine);
-
- *cEnd = '\0';
- processCommand();
-
- // Copy rest of line (if any) to start of buffer
- strncpy(_currentLine, cEnd + 1, sizeof(_currentLine));
-
- cStart = strchr(_currentLine, '[');
- }
-
- if (_currentLine[0]) {
- processText();
- break;
- }
-
- } else {
- processText();
- break;
- }
- }
-}
-
-void TextView::processCommand() {
- Common::String scriptLine(_currentLine + 1);
- scriptLine.toUppercase();
- const char *paramP;
- const char *commandStr = scriptLine.c_str();
-
- if (!strncmp(commandStr, "BACKGROUND", 10)) {
- // Set the background
- paramP = commandStr + 10;
- _screenId = getParameter(&paramP);
-
- } else if (!strncmp(commandStr, "GO", 2)) {
- _animating = true;
-
- } else if (!strncmp(commandStr, "PAN", 3)) {
- // Set panning values
- paramP = commandStr + 3;
- int panX = getParameter(&paramP);
- int panY = getParameter(&paramP);
- int panSpeed = getParameter(&paramP);
-
- if ((panX != 0) || (panY != 0)) {
- _pan = Common::Point(panX, panY);
- _panSpeed = panSpeed;
- }
-
- } else if (!strncmp(commandStr, "DRIVER", 6)) {
- // Set the driver to use
- paramP = commandStr + 7;
-
- if (!strncmp(paramP, "#SOUND.00", 9)) {
- int driverNum = paramP[9] - '0';
- _vm->_sound->init(driverNum);
- }
- } else if (!strncmp(commandStr, "SOUND", 5)) {
- // Set sound number
- paramP = commandStr + 5;
- int soundId = getParameter(&paramP);
- _vm->_sound->command(soundId);
-
- } else if (!strncmp(commandStr, "COLOR", 5) && ((commandStr[5] == '0') ||
- (commandStr[5] == '1'))) {
- // Set the text colors
- int index = commandStr[5] - '0';
- paramP = commandStr + 6;
-
- byte palEntry[3];
- palEntry[0] = getParameter(&paramP) << 2;
- palEntry[1] = getParameter(&paramP) << 2;
- palEntry[2] = getParameter(&paramP) << 2;
- _vm->_palette->setPalette(&palEntry[0], 5 + index, 1);
-
- } else if (!strncmp(commandStr, "SPARE", 5)) {
- // Sets a secondary background number that can be later switched in with a PAGE command
- paramP = commandStr + 6;
- int spareIndex = commandStr[5] - '0';
- if ((spareIndex >= 0) && (spareIndex <= 9)) {
- int screenId = getParameter(&paramP);
-
- _spareScreens[spareIndex] = screenId;
- }
-
- } else if (!strncmp(commandStr, "PAGE", 4)) {
- // Signals to change to a previous specified secondary background
- paramP = commandStr + 4;
- int spareIndex = getParameter(&paramP);
-
- // Only allow background switches if one isn't currently in progress
- if (!_spareScreen && (_spareScreens[spareIndex] != 0)) {
- _spareScreen = new MSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
- //_spareScreen->loadBackground(_spareScreens[spareIndex], &_bgSpare);
-
- _translationX = 0;
- }
-
- } else {
- error("Unknown response command: '%s'", commandStr);
- }
-}
-
-int TextView::getParameter(const char **paramP) {
- if ((**paramP != '=') && (**paramP != ','))
- return 0;
-
- int result = 0;
- ++*paramP;
- while ((**paramP >= '0') && (**paramP <= '9')) {
- result = result * 10 + (**paramP - '0');
- ++*paramP;
- }
-
- return result;
-}
-
-void TextView::processText() {
- int lineWidth, xStart;
-
- if (!strcmp(_currentLine, "***")) {
- // Special signifier for end of script
- _scrollCount = _font->getHeight() * 13;
- _lineY = -1;
- return;
- }
-
- _lineY = 0;
-
- // Lines are always centered, except if line contains a '@', in which case the
- // '@' marks the position that must be horizontally centered
- char *centerP = strchr(_currentLine, '@');
- if (centerP) {
- *centerP = '\0';
- xStart = (MADS_SCREEN_WIDTH / 2) - _font->getWidth(_currentLine);
-
- // Delete the @ character and shift back the remainder of the string
- char *p = centerP + 1;
- if (*p == ' ') ++p;
- strcpy(centerP, p);
-
- } else {
- lineWidth = _font->getWidth(_currentLine);
- xStart = (MADS_SCREEN_WIDTH - lineWidth) / 2;
- }
-
- // Add the new line to the list of pending lines
- TextLine tl;
- tl._pos = Common::Point(xStart, 155);
- tl._line = _currentLine;
- _textLines.push_back(tl);
-}
-
-void TextView::display() {
- resetPalette();
-
- FullScreenDialog::display();
- _sceneChanged = true;
-}
-
-void TextView::resetPalette() {
- _vm->_palette->resetGamePalette(8, 8);
- _vm->_palette->setEntry(5, 0, 63, 63);
- _vm->_palette->setEntry(6, 0, 45, 45);
-}
-
-void TextView::doFrame() {
- Scene &scene = _vm->_game->_scene;
- if (!_animating)
- return;
-
- // Only update state if wait period has expired
- uint32 currTime = g_system->getMillis();
-
- // If a screen transition is in progress and it's time for another column, handle it
- if (_spareScreen) {
- byte *srcP = _spareScreen->getBasePtr(_translationX, 0);
- byte *destP = scene._backgroundSurface.getBasePtr(_translationX, 0);
-
- for (int y = 0; y < MADS_SCENE_HEIGHT; ++y, srcP += _spareScreen->w,
- destP += MADS_SCREEN_WIDTH) {
- *destP = *srcP;
- }
-
- if (++_translationX >= MADS_SCREEN_WIDTH) {
- // Surface transition is complete
- /*
- delete _spareScreen;
- _spareScreen = nullptr;
-
-// _vm->_palette->deleteRange(_bgCurrent);
- delete _bgCurrent;
- _bgCurrent = _bgSpare;
- _bgSpare = nullptr;
- */
- }
- }
-
- // Make sure it's time for an update
- if (currTime < _scrollTimeout)
- return;
- _scrollTimeout = g_system->getMillis() + TEXT_ANIMATION_DELAY;
- _redrawFlag = true;
-
- // If any panning values are set, pan the background surface
- if ((_pan.x != 0) || (_pan.y != 0)) {
- if (_panCountdown > 0) {
- --_panCountdown;
- return;
- }
-
- // Handle horizontal panning
- if (_pan.x != 0) {
- byte *lineTemp = new byte[_pan.x];
- for (int y = 0; y < MADS_SCENE_HEIGHT; ++y) {
- byte *pixelsP = (byte *)scene._backgroundSurface.getBasePtr(0, y);
-
- // Copy the first X pixels into temp buffer, move the rest of the line
- // to the start of the line, and then move temp buffer pixels to end of line
- Common::copy(pixelsP, pixelsP + _pan.x, lineTemp);
- Common::copy(pixelsP + _pan.x, pixelsP + MADS_SCREEN_WIDTH, pixelsP);
- Common::copy(lineTemp, lineTemp + _pan.x, pixelsP + MADS_SCREEN_WIDTH - _pan.x);
- }
-
- delete[] lineTemp;
- }
-
- // Handle vertical panning
- if (_pan.y != 0) {
- // Store the bottom Y lines into a temp buffer, move the rest of the lines down,
- // and then copy the stored lines back to the top of the screen
- byte *linesTemp = new byte[_pan.y * MADS_SCREEN_WIDTH];
- byte *pixelsP = (byte *)scene._backgroundSurface.getBasePtr(0, MADS_SCENE_HEIGHT - _pan.y);
- Common::copy(pixelsP, pixelsP + MADS_SCREEN_WIDTH * _pan.y, linesTemp);
-
- for (int y = MADS_SCENE_HEIGHT - 1; y >= _pan.y; --y) {
- byte *destP = (byte *)scene._backgroundSurface.getBasePtr(0, y);
- byte *srcP = (byte *)scene._backgroundSurface.getBasePtr(0, y - _pan.y);
- Common::copy(srcP, srcP + MADS_SCREEN_WIDTH, destP);
- }
-
- Common::copy(linesTemp, linesTemp + _pan.y * MADS_SCREEN_WIDTH,
- (byte *)scene._backgroundSurface.getPixels());
- delete[] linesTemp;
- }
-
- // Flag for a full screen refresh
- scene._spriteSlots.fullRefresh();
- }
-
- // Scroll all active text lines up
- scene._textDisplay.reset();
- for (int i = _textLines.size() - 1; i >= 0; --i) {
- TextLine &tl = _textLines[i];
- tl._pos.y--;
- if (tl._pos.y < 0) {
- _textLines.remove_at(i);
- } else {
- scene._textDisplay.add(tl._pos.x, tl._pos.y, 0x605, -1, tl._line, _font);
- }
- }
-
- if (_scrollCount > 0) {
- // Handling final scrolling of text off of screen
- if (--_scrollCount == 0) {
- scriptDone();
- return;
- }
- } else {
- // Handling a text row
- if (++_lineY == (_font->getHeight() + TEXTVIEW_LINE_SPACING))
- processLines();
- }
-}
-
-void TextView::scriptDone() {
- _breakFlag = true;
-}
-
-/*------------------------------------------------------------------------*/
-
-char AnimationView::_resourceName[100];
-
-void AnimationView::execute(MADSEngine *vm, const Common::String &resName) {
- assert(resName.size() < 100);
- strncpy(_resourceName, resName.c_str(), sizeof(_resourceName));
- vm->_dialogs->_pendingDialog = DIALOG_ANIMVIEW;
-}
-
-AnimationView::AnimationView(MADSEngine *vm) : MenuView(vm) {
- _soundDriverLoaded = false;
- _previousUpdate = 0;
-}
-
-void AnimationView::load() {
- Common::String resName(_resourceName);
- if (!resName.hasSuffix("."))
- resName += ".res";
-
- if (!_script.open(resName))
- error("Could not open resource %s", resName.c_str());
-
- processLines();
-}
-
-bool AnimationView::onEvent(Common::Event &event) {
- // Wait for the Escape key or a mouse press
- if (((event.type == Common::EVENT_KEYDOWN) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) ||
- (event.type == Common::EVENT_RBUTTONUP)) {
- scriptDone();
- return true;
- }
-
- return false;
-}
-
-void AnimationView::doFrame() {
- Scene &scene = _vm->_game->_scene;
- int bgNumber = 0;
-
- // Only update state if wait period has expired
- if (_previousUpdate > 0) {
- if (g_system->getMillis() - _previousUpdate < 3000) {
- return;
- } else {
- // time for an update
- _previousUpdate = g_system->getMillis();
- }
- } else {
- _previousUpdate = g_system->getMillis();
- return;
- }
-
- char bgFile[10];
- strncpy(bgFile, _currentFile, 5);
- bgFile[0] = bgFile[2];
- bgFile[1] = bgFile[3];
- bgFile[2] = bgFile[4];
- bgFile[3] = '\0';
- bgNumber = atoi(bgFile);
- sprintf(bgFile, "rm%i.art", bgNumber);
-
- // Not all scenes have a background. If there is one, refresh it
- if (Common::File::exists(bgFile)) {
- _vm->_palette->resetGamePalette(4, 8);
- SceneInfo *sceneInfo = SceneInfo::init(_vm);
- sceneInfo->load(bgNumber, 0, Common::String(), 0, scene._depthSurface,
- scene._backgroundSurface);
- }
-
- // Read next line
- processLines();
-}
+void RexAnimationView::scriptDone() {
+ AnimationView::scriptDone();
-void AnimationView::scriptDone() {
- _breakFlag = true;
- _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
-}
-
-void AnimationView::processLines() {
- if (_script.eos()) {
- // end of script, end animation
- scriptDone();
- return;
- }
-
- while (!_script.eos()) {
- _script.readLine(_currentLine, 79);
-
- // Process the line
- char *cStart = strchr(_currentLine, '-');
- if (cStart) {
- while (cStart) {
- // Loop for possible multiple commands on one line
- char *cEnd = strchr(_currentLine, ' ');
- if (!cEnd)
- error("Unterminated command '%s' in response file", _currentLine);
-
- *cEnd = '\0';
- processCommand();
-
- // Copy rest of line (if any) to start of buffer
- // Don't use strcpy() here, because if the
- // rest of the line is the longer of the two
- // strings, the memory areas will overlap.
- memmove(_currentLine, cEnd + 1, strlen(cEnd + 1) + 1);
-
- cStart = strchr(_currentLine, '-');
- }
-
- if (_currentLine[0]) {
- sprintf(_currentFile, "%s", _currentLine);
- //printf("File: %s\n", _currentLine);
- break;
- }
-
- } else {
- sprintf(_currentFile, "%s", _currentLine);
- warning("File: %s\n", _currentLine);
- break;
- }
- }
-}
-
-void AnimationView::processCommand() {
- Common::String commandLine(_currentLine + 1);
- commandLine.toUppercase();
- const char *commandStr = commandLine.c_str();
- const char *param = commandStr;
-
- if (!strncmp(commandStr, "X", 1)) {
- //printf("X ");
- } else if (!strncmp(commandStr, "W", 1)) {
- //printf("W ");
- } else if (!strncmp(commandStr, "R", 1)) {
- param = param + 2;
- //printf("R:%s ", param);
- } else if (!strncmp(commandStr, "O", 1)) {
- // Set the transition effect
- param = param + 2;
- _vm->_game->_fx = (ScreenTransition)atoi(param);
- } else {
- error("Unknown response command: '%s'", commandStr);
+ Common::String s = getResourceName();
+ if (s == "rexend1") {
+ TextView::execute(_vm, "ending1");
+ } else if (s == "rexend2") {
+ TextView::execute(_vm, "ending2");
+ } else if (s == "rexend3") {
+ TextView::execute(_vm, "credits");
}
}
diff --git a/engines/mads/nebular/menu_nebular.h b/engines/mads/nebular/menu_nebular.h
index 767183c4b9..77b8b6fc6e 100644
--- a/engines/mads/nebular/menu_nebular.h
+++ b/engines/mads/nebular/menu_nebular.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "mads/game.h"
+#include "mads/menu_views.h"
#include "mads/msurface.h"
#include "mads/nebular/dialogs_nebular.h"
@@ -36,22 +37,6 @@ namespace Nebular {
enum MADSGameAction { START_GAME, RESUME_GAME, SHOW_INTRO, CREDITS, QUOTES, EXIT };
-class MenuView: public FullScreenDialog {
-protected:
- bool _breakFlag;
- bool _redrawFlag;
-
- virtual void doFrame() = 0;
-
- virtual void display();
-public:
- MenuView(MADSEngine *vm);
-
- virtual ~MenuView() {}
-
- virtual void show();
-};
-
class MainMenu: public MenuView {
private:
SpriteAsset *_menuItems[7];
@@ -95,6 +80,8 @@ private:
* Add a sprite slot for the current menuitem frame
*/
void addSpriteSlot();
+
+ bool shouldShowQuotes();
protected:
/**
* Display the menu
@@ -143,116 +130,16 @@ public:
void show();
};
-struct TextLine {
- Common::Point _pos;
- Common::String _line;
-};
-
-/**
- * Scrolling text view
- */
-class TextView : public MenuView {
-private:
- static char _resourceName[100];
-
- bool _animating;
- bool _sceneChanged;
- Common::Array<TextLine> _textLines;
- Common::Point _pan;
- int _panSpeed;
- int _spareScreens[10];
- int _scrollCount;
- int _lineY;
- uint32 _scrollTimeout;
- int _panCountdown;
- int _translationX;
- Common::File _script;
- char _currentLine[80];
- MSurface *_spareScreen;
- Font *_font;
-private:
- /**
- * Load the text resource
- */
- void load();
-
- /**
- * Process the lines
- */
- void processLines();
-
- /**
- * Process a command from the script file
- */
- void processCommand();
-
- /**
- * Process text from the script file
- */
- void processText();
-
- /**
- * Get a parameter from line
- */
- int getParameter(const char **paramP);
-
- /**
- * Called when the script is finished
- */
- void scriptDone();
-
- /**
- * Reset the game palette
- */
- void resetPalette();
+class RexAnimationView : public AnimationView {
protected:
- virtual void display();
-
- virtual void doFrame();
+ virtual void scriptDone();
public:
- /**
- * Queue the given text resource for display
- */
- static void execute(MADSEngine *vm, const Common::String &resName);
-
- TextView(MADSEngine *vm);
-
- virtual ~TextView();
+ RexAnimationView(MADSEngine *vm) : AnimationView(vm) {}
};
-/**
-* Animation cutscene view
-*/
-class AnimationView : public MenuView {
-private:
- static char _resourceName[100];
-
- Common::File _script;
- uint32 _previousUpdate;
- char _currentLine[80];
- char _currentFile[10];
- bool _soundDriverLoaded;
-private:
- void load();
-
- void processLines();
-
- void processCommand();
-
- void scriptDone();
-protected:
- virtual void doFrame();
-
- virtual bool onEvent(Common::Event &event);
+class RexTextView : public TextView {
public:
- /**
- * Queue the given text resource for display
- */
- static void execute(MADSEngine *vm, const Common::String &resName);
-
- AnimationView(MADSEngine *vm);
-
- virtual ~AnimationView() {}
+ RexTextView(MADSEngine *vm) : TextView(vm) {}
};
} // End of namespace Nebular
diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp
index 5a67d1541f..66d8294fc6 100644
--- a/engines/mads/nebular/nebular_scenes5.cpp
+++ b/engines/mads/nebular/nebular_scenes5.cpp
@@ -2847,8 +2847,6 @@ void Scene551::actions() {
_vm->_dialogs->show(55113);
else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER))
_vm->_dialogs->show(55114);
- else if (_action.isAction(VERB_LOOK, NOUN_BUILDING))
- _vm->_dialogs->show(55115);
else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST)) {
if (_game._visitedScenes.exists(505))
_vm->_dialogs->show(55116);
diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp
index d33675c578..13ee1a3dc1 100644
--- a/engines/mads/nebular/nebular_scenes6.cpp
+++ b/engines/mads/nebular/nebular_scenes6.cpp
@@ -643,7 +643,8 @@ void Scene603::actions() {
_game._player._visible = true;
_game._player._stepEnabled = true;
}
- }
+ } else
+ _vm->_dialogs->show(60323);
} else if (_action._lookFlag)
_vm->_dialogs->show(60310);
else if (_action.isAction(VERB_LOOK, NOUN_BED))
@@ -670,8 +671,6 @@ void Scene603::actions() {
_vm->_dialogs->show(60321);
else if (_action.isAction(VERB_TAKE, NOUN_PERFUME))
_vm->_dialogs->show(60322);
- else if (_action.isAction(VERB_TAKE, NOUN_NOTE))
- _vm->_dialogs->show(60323);
else if (_action.isAction(VERB_LOOK, NOUN_NOTE)) {
if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId)
_vm->_dialogs->show(60324);
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 4c6070b528..0a054440b2 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -24,6 +24,7 @@
#include "audio/decoders/raw.h"
#include "common/algorithm.h"
#include "common/debug.h"
+#include "common/md5.h"
#include "common/memstream.h"
#include "mads/sound.h"
#include "mads/nebular/sound_nebular.h"
@@ -149,7 +150,7 @@ AdlibSample::AdlibSample(Common::SeekableReadStream &s) {
/*-----------------------------------------------------------------------*/
-ASound::ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffset) {
+ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, int dataOffset) {
// Open up the appropriate sound file
if (!_soundFile.open(filename))
error("Could not open file - %s", filename.c_str());
@@ -197,8 +198,7 @@ ASound::ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffs
// Store passed parameters, and setup OPL
_dataOffset = dataOffset;
_mixer = mixer;
- _opl = OPL::Config::create();
- assert(_opl);
+ _opl = opl;
_opl->init(getRate());
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
@@ -217,7 +217,32 @@ ASound::~ASound() {
delete[] (*i)._data;
_mixer->stopHandle(_soundHandle);
- delete _opl;
+}
+
+void ASound::validate() {
+ Common::File f;
+ static const char *const MD5[] = {
+ "205398468de2c8873b7d4d73d5be8ddc",
+ "f9b2d944a2fb782b1af5c0ad592306d3",
+ "7431f8dad77d6ddfc24e6f3c0c4ac7df",
+ "eb1f3f5a4673d3e73d8ac1818c957cf4",
+ "f936dd853073fa44f3daac512e91c476",
+ "3dc139d3e02437a6d9b732072407c366",
+ "af0edab2934947982e9a405476702e03",
+ "8cbc25570b50ba41c9b5361cad4fbedc",
+ "a31e4783e098f633cbb6689adb41dd4f"
+ };
+
+ for (int i = 1; i <= 9; ++i) {
+ Common::String filename = Common::String::format("ASOUND.00%d", i);
+ if (!f.open(filename))
+ error("Could not process - %s", filename.c_str());
+ Common::String md5str = Common::computeStreamMD5AsString(f, 8192);
+ f.close();
+
+ if (md5str != MD5[i - 1])
+ error("Invalid sound file - %s", filename.c_str());
+ }
}
void ASound::adlibInit() {
@@ -941,8 +966,8 @@ const ASound1::CommandPtr ASound1::_commandList[42] = {
&ASound1::command40, &ASound1::command41
};
-ASound1::ASound1(Audio::Mixer *mixer)
- : ASound(mixer, "asound.001", 0x1520) {
+ASound1::ASound1(Audio::Mixer *mixer, FM_OPL *opl)
+ : ASound(mixer, opl, "asound.001", 0x1520) {
_cmd23Toggle = false;
// Load sound samples
@@ -1242,7 +1267,7 @@ const ASound2::CommandPtr ASound2::_commandList[44] = {
&ASound2::command40, &ASound2::command41, &ASound2::command42, &ASound2::command43
};
-ASound2::ASound2(Audio::Mixer *mixer) : ASound(mixer, "asound.002", 0x15E0) {
+ASound2::ASound2(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
_command12Param = 0xFD;
// Load sound samples
@@ -1613,7 +1638,7 @@ const ASound3::CommandPtr ASound3::_commandList[61] = {
&ASound3::command60
};
-ASound3::ASound3(Audio::Mixer *mixer) : ASound(mixer, "asound.003", 0x15B0) {
+ASound3::ASound3(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.003", 0x15B0) {
_command39Flag = false;
// Load sound samples
@@ -2017,7 +2042,7 @@ const ASound4::CommandPtr ASound4::_commandList[61] = {
&ASound4::command60
};
-ASound4::ASound4(Audio::Mixer *mixer) : ASound(mixer, "asound.004", 0x14F0) {
+ASound4::ASound4(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.004", 0x14F0) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 210; ++i)
@@ -2273,7 +2298,7 @@ const ASound5::CommandPtr ASound5::_commandList[42] = {
&ASound5::command40, &ASound5::command41
};
-ASound5::ASound5(Audio::Mixer *mixer) : ASound(mixer, "asound.002", 0x15E0) {
+ASound5::ASound5(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x144);
for (int i = 0; i < 164; ++i)
@@ -2514,7 +2539,7 @@ const ASound6::CommandPtr ASound6::_commandList[30] = {
&ASound6::nullCommand, &ASound6::command29
};
-ASound6::ASound6(Audio::Mixer *mixer) : ASound(mixer, "asound.006", 0x1390) {
+ASound6::ASound6(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.006", 0x1390) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 200; ++i)
@@ -2670,7 +2695,7 @@ const ASound7::CommandPtr ASound7::_commandList[38] = {
&ASound7::command36, &ASound7::command37
};
-ASound7::ASound7(Audio::Mixer *mixer) : ASound(mixer, "asound.007", 0x1460) {
+ASound7::ASound7(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.007", 0x1460) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 214; ++i)
@@ -2876,7 +2901,7 @@ const ASound8::CommandPtr ASound8::_commandList[38] = {
&ASound8::command36, &ASound8::command37
};
-ASound8::ASound8(Audio::Mixer *mixer) : ASound(mixer, "asound.008", 0x1490) {
+ASound8::ASound8(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.008", 0x1490) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 174; ++i)
@@ -3132,7 +3157,7 @@ const ASound9::CommandPtr ASound9::_commandList[52] = {
&ASound9::command48, &ASound9::command49, &ASound9::command50, &ASound9::command51
};
-ASound9::ASound9(Audio::Mixer *mixer) : ASound(mixer, "asound.009", 0x16F0) {
+ASound9::ASound9(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.009", 0x16F0) {
_v1 = _v2 = 0;
_soundPtr = nullptr;
@@ -3143,7 +3168,7 @@ ASound9::ASound9(Audio::Mixer *mixer) : ASound(mixer, "asound.009", 0x16F0) {
}
int ASound9::command(int commandId, int param) {
- if (commandId > 60)
+ if (commandId > 51)
return 0;
_commandParam = param;
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index 744467b45e..ccfd40ad52 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -305,10 +305,12 @@ public:
public:
/**
* Constructor
+ * @param mixer Mixer
+ * @param opl OPL
* @param filename Specifies the adlib sound player file to use
* @param dataOffset Offset in the file of the data segment
*/
- ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffset);
+ ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, int dataOffset);
/**
* Destructor
@@ -316,6 +318,11 @@ public:
virtual ~ASound();
/**
+ * Validates the Adlib sound files
+ */
+ static void validate();
+
+ /**
* Execute a player command. Most commands represent sounds to play, but some
* low number commands also provide control operations.
* @param commandId Player ommand to execute.
@@ -408,7 +415,7 @@ private:
void command111213();
int command2627293032();
public:
- ASound1(Audio::Mixer *mixer);
+ ASound1(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -460,7 +467,7 @@ private:
void command9Randomize();
void command9Apply(byte *data, int val, int incr);
public:
- ASound2(Audio::Mixer *mixer);
+ ASound2(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -520,7 +527,7 @@ private:
void command9Randomize();
void command9Apply(byte *data, int val, int incr);
public:
- ASound3(Audio::Mixer *mixer);
+ ASound3(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -558,7 +565,7 @@ private:
void method1();
public:
- ASound4(Audio::Mixer *mixer);
+ ASound4(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -604,7 +611,7 @@ private:
int command42();
int command43();
public:
- ASound5(Audio::Mixer *mixer);
+ ASound5(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -633,7 +640,7 @@ private:
int command25();
int command29();
public:
- ASound6(Audio::Mixer *mixer);
+ ASound6(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -665,7 +672,7 @@ private:
int command36();
int command37();
public:
- ASound7(Audio::Mixer *mixer);
+ ASound7(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -708,7 +715,7 @@ private:
void method1(byte *pData);
void adjustRange(byte *pData, byte v, int incr);
public:
- ASound8(Audio::Mixer *mixer);
+ ASound8(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
@@ -767,7 +774,7 @@ private:
int command59();
int command60();
public:
- ASound9(Audio::Mixer *mixer);
+ ASound9(Audio::Mixer *mixer, FM_OPL *opl);
virtual int command(int commandId, int param);
};
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
index eedbf36ddd..1787b3c298 100644
--- a/engines/mads/palette.cpp
+++ b/engines/mads/palette.cpp
@@ -143,7 +143,7 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) {
for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) {
bool changed = false;
- int newPalIndex = -1;
+ int newPalIndex = 0xFF;
int v1 = palRange[palIndex]._v2;
if (palette[v1]._flags & 8) {
@@ -229,7 +229,10 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) {
// In at least scene 318, when the doctor knocks you with the blackjack,
// the changed flag can be false
//assert(changed);
- assert(newPalIndex != -1);
+
+ // CHECKME: When pressing on F1 in the first screen, newPalIndex is set to 0xFF at this point
+ // which is a valid value for the index. Maybe a better check would be "< 256" ?
+ //assert(newPalIndex != -1);
int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0;
@@ -314,6 +317,62 @@ int PaletteUsage::rgbFactor(byte *palEntry, RGB6 &pal6) {
return total;
}
+int PaletteUsage::checkRGB(const byte *rgb, int palStart, bool flag, int *palIndex) {
+ Palette &palette = *_vm->_palette;
+ bool match = false;
+ int result;
+ if (palStart >= 0) {
+ result = palStart;
+ } else {
+ result = -1;
+ for (int i = 0; i < palette._highRange; ++i) {
+ if (!palette._rgbList[i]) {
+ result = i;
+ break;
+ }
+ }
+ }
+
+ if (result >= 0) {
+ int mask = 1 << result;
+ byte *palP = &palette._mainPalette[0];
+ uint32 *flagsP = &palette._palFlags[0];
+
+ for (; flagsP < &palette._palFlags[PALETTE_COUNT]; ++flagsP, ++result) {
+ if ((!(*flagsP & 1) || flag) && !(*flagsP & 2)) {
+ if (!memcmp(palP, rgb, 3)) {
+ *flagsP |= mask;
+
+ if (palIndex)
+ *palIndex = result;
+ match = true;
+ break;
+ }
+ }
+ }
+
+ if (!match) {
+ palP = &palette._mainPalette[0];
+ flagsP = &palette._palFlags[0];
+
+ for (int i = 0; i < PALETTE_COUNT; ++i, palP += 3, ++flagsP) {
+ if (!*flagsP) {
+ Common::copy(rgb, rgb + 3, palP);
+ *flagsP |= mask;
+
+ if (palIndex)
+ *palIndex = i;
+ match = true;
+ break;
+ }
+ }
+ }
+ }
+
+ assert(match);
+ return result;
+}
+
/*------------------------------------------------------------------------*/
void RGBList::clear() {
diff --git a/engines/mads/palette.h b/engines/mads/palette.h
index 9b8b7146db..27d25f266b 100644
--- a/engines/mads/palette.h
+++ b/engines/mads/palette.h
@@ -136,6 +136,8 @@ public:
void updateUsage(Common::Array<int> &usageList, int sceneUsageIndex);
void resetPalFlags(int idx);
+
+ int checkRGB(const byte *rgb, int palStart, bool flag, int *palIndex);
};
class RGBList {
diff --git a/engines/mads/phantom/game_phantom.cpp b/engines/mads/phantom/game_phantom.cpp
index ba2179fcbf..0b2531ef65 100644
--- a/engines/mads/phantom/game_phantom.cpp
+++ b/engines/mads/phantom/game_phantom.cpp
@@ -50,11 +50,12 @@ void GamePhantom::startGame() {
}
void GamePhantom::initializeGlobals() {
- //int count, count2;
- //int bad;
-
_globals.reset();
- //_globals[kTalkInanimateCount] = 8;
+
+ warning("TODO: sub_316DA()");
+
+ _player._facing = FACING_NORTH;
+ _player._turnToFacing = FACING_NORTH;
/* Section #1 variables */
// TODO
@@ -74,11 +75,7 @@ void GamePhantom::initializeGlobals() {
/* Section #9 variables */
// TODO
- _player._facing = FACING_NORTH;
- _player._turnToFacing = FACING_NORTH;
-
- //Player::preloadSequences("RXM", 1);
- //Player::preloadSequences("ROX", 1);
+ Player::preloadSequences("RAL", 1);
}
void GamePhantom::setSectionHandler() {
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index ad24dd4f60..18ceb3c813 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -360,6 +360,9 @@ void Scene::loop() {
if (_vm->_dialogs->_pendingDialog != DIALOG_NONE && !_vm->_game->_trigger
&& _vm->_game->_player._stepEnabled)
_reloadSceneFlag = true;
+
+ if (_vm->_game->_winStatus)
+ break;
}
}
diff --git a/engines/mads/scene.h b/engines/mads/scene.h
index ee7864cfee..9fd99ad8e5 100644
--- a/engines/mads/scene.h
+++ b/engines/mads/scene.h
@@ -52,11 +52,6 @@ private:
*/
void loadVocabStrings();
- /*
- * Initializes the data for palette animation within the scene
- */
- void initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag);
-
/**
* Handles a single frame within the game scene
*/
@@ -204,6 +199,11 @@ public:
*/
void drawElements(ScreenTransition transitionType, bool surfaceFlag);
+ /*
+ * Initializes the data for palette animation within the scene
+ */
+ void initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag);
+
/**
* Handles cycling palette colors for the scene
*/
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
index e874468345..b0a5aa35c6 100644
--- a/engines/mads/scene_data.cpp
+++ b/engines/mads/scene_data.cpp
@@ -217,7 +217,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
int width = _width;
int height = _height;
- if (!bgSurface.getPixels()) {
+ if (!bgSurface.getPixels() || (bgSurface.w != width) || (bgSurface.h != height)) {
bgSurface.setSize(width, height);
}
@@ -232,11 +232,11 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
infoFile.close();
if (_vm->getGameID() == GType_RexNebular) {
- loadMadsV1Background(sceneId, resName, flags, bgSurface);
- loadPalette(sceneId, _artFileNum, resName, flags, bgSurface);
+ loadMadsV1Background(_artFileNum, resName, flags, bgSurface);
+ loadPalette(_sceneId, _artFileNum, resName, flags, bgSurface);
} else {
- loadMadsV2Background(sceneId, resName, flags, bgSurface);
- loadPalette(sceneId, sceneId, resName, flags, bgSurface);
+ loadMadsV2Background(_sceneId, resName, flags, bgSurface);
+ loadPalette(_sceneId, _sceneId, resName, flags, bgSurface);
}
Common::Array<SpriteAsset *> spriteSets;
@@ -299,6 +299,7 @@ void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &r
delete stream;
// Copy out the palette animation data
+ _paletteCycles.clear();
for (uint i = 0; i < artHeader._paletteCycles.size(); ++i)
_paletteCycles.push_back(artHeader._paletteCycles[i]);
@@ -333,7 +334,7 @@ void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName,
// Get the ART resource
if (sceneFlag) {
- resourceName = Resources::formatName(RESPREFIX_RM, _artFileNum, ".ART");
+ resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".ART");
} else {
resourceName = "*" + Resources::formatResource(resName, resName);
}
@@ -342,13 +343,33 @@ void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName,
File artFile(resourceName);
MadsPack artResource(&artFile);
- // Read in the background surface data
- assert(_width == bgSurface.w && _height == bgSurface.h);
+ // Read inhh the background surface data
+ assert(_width && _height == bgSurface.h);
stream = artResource.getItemStream(1);
stream->read(bgSurface.getPixels(), bgSurface.w * bgSurface.h);
+ delete stream;
+
+ if (flags & SCENEFLAG_TRANSLATE) {
+ // Load in the palette and translate it
+ Common::SeekableReadStream *palStream = artResource.getItemStream(0);
+ Common::Array<RGB6> palette;
+
+ _width = palStream->readUint16LE();
+ _height = palStream->readUint16LE();
+
+ int numColors = palStream->readUint16LE();
+ assert(numColors <= 252);
+ palette.resize(numColors);
+ for (int i = 0; i < numColors; ++i)
+ palette[i].load(palStream);
+ delete palStream;
+
+ // Translate the surface
+ _vm->_palette->_paletteUsage.process(palette, 0);
+ bgSurface.translate(palette);
+ }
// Close the ART file
- delete stream;
artFile.close();
}
diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h
index 783a9ab8a9..41e094b8f5 100644
--- a/engines/mads/scene_data.h
+++ b/engines/mads/scene_data.h
@@ -55,7 +55,8 @@ class SpriteSlot;
enum {
SCENEFLAG_DITHER = 0x01, // Dither to 16 colors
- SCENEFLAG_LOAD_SHADOW = 0x10 // Load hard shadows
+ SCENEFLAG_LOAD_SHADOW = 0x10, // Load hard shadows
+ SCENEFLAG_TRANSLATE = 0x10000 // Translate palette of loaded background
};
class VerbInit {
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
index 590e63ac9e..c9a0863d85 100644
--- a/engines/mads/screen.cpp
+++ b/engines/mads/screen.cpp
@@ -212,7 +212,7 @@ void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common:
Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y,
srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y);
- Common::Point destPos(bounds.left, bounds.top);
+ Common::Point destPos(srcBounds.left, srcBounds.top);
if ((*this)[i]._active && bounds.isValidRect()) {
srcSurface->copyTo(destSurface, bounds, destPos);
diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp
index 35d948e0b0..1652550ba3 100644
--- a/engines/mads/sound.cpp
+++ b/engines/mads/sound.cpp
@@ -36,10 +36,27 @@ SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer) {
_pollSoundEnabled = false;
_soundPollFlag = false;
_newSoundsPaused = false;
+
+ _opl = OPL::Config::create();
+ _opl->init(11025);
+
+ // Validate sound files
+ switch (_vm->getGameID()) {
+ case GType_RexNebular:
+ Nebular::ASound::validate();
+ break;
+ default:
+ break;
+ }
}
SoundManager::~SoundManager() {
- delete _driver;
+ if (_driver) {
+ _driver->stop();
+ delete _driver;
+ }
+
+ delete _opl;
}
void SoundManager::init(int sectionNumber) {
@@ -49,31 +66,31 @@ void SoundManager::init(int sectionNumber) {
case GType_RexNebular:
switch (sectionNumber) {
case 1:
- _driver = new Nebular::ASound1(_mixer);
+ _driver = new Nebular::ASound1(_mixer, _opl);
break;
case 2:
- _driver = new Nebular::ASound2(_mixer);
+ _driver = new Nebular::ASound2(_mixer, _opl);
break;
case 3:
- _driver = new Nebular::ASound3(_mixer);
+ _driver = new Nebular::ASound3(_mixer, _opl);
break;
case 4:
- _driver = new Nebular::ASound4(_mixer);
+ _driver = new Nebular::ASound4(_mixer, _opl);
break;
case 5:
- _driver = new Nebular::ASound5(_mixer);
+ _driver = new Nebular::ASound5(_mixer, _opl);
break;
case 6:
- _driver = new Nebular::ASound6(_mixer);
+ _driver = new Nebular::ASound6(_mixer, _opl);
break;
case 7:
- _driver = new Nebular::ASound7(_mixer);
+ _driver = new Nebular::ASound7(_mixer, _opl);
break;
case 8:
- _driver = new Nebular::ASound8(_mixer);
+ _driver = new Nebular::ASound8(_mixer, _opl);
break;
case 9:
- _driver = new Nebular::ASound9(_mixer);
+ _driver = new Nebular::ASound9(_mixer, _opl);
break;
default:
_driver = nullptr;
diff --git a/engines/mads/sound.h b/engines/mads/sound.h
index 9a251f9dd0..72bb21a812 100644
--- a/engines/mads/sound.h
+++ b/engines/mads/sound.h
@@ -37,6 +37,7 @@ class SoundManager {
private:
MADSEngine *_vm;
Audio::Mixer *_mixer;
+ FM_OPL *_opl;
Nebular::ASound *_driver;
bool _pollSoundEnabled;
bool _soundPollFlag;
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
index cd358077b5..fd73930475 100644
--- a/engines/mads/sprites.cpp
+++ b/engines/mads/sprites.cpp
@@ -262,7 +262,7 @@ void SpriteSlots::drawBackground() {
scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface,
-1, false, frame->getTransparencyIndex());
} else {
- error("Unsupported depth style");
+ frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex());
}
}
}
@@ -404,9 +404,9 @@ void SpriteSets::remove(int idx) {
delete (*this)[idx];
(*this)[idx] = nullptr;
} else {
- while (size() > 0 && (*this)[size() - 1] == nullptr) {
+ do {
remove_at(size() - 1);
- }
+ } while (size() > 0 && (*this)[size() - 1] == nullptr);
}
if (_assetCount > 0)
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
index f251441e40..89044c9bf1 100644
--- a/engines/mads/user_interface.h
+++ b/engines/mads/user_interface.h
@@ -225,7 +225,7 @@ public:
/**
* Loads an interface from a specified resource
*/
- void load(const Common::String &resName);
+ virtual void load(const Common::String &resName);
/**
* Set up the interface
diff --git a/engines/prince/animation.cpp b/engines/prince/animation.cpp
new file mode 100644
index 0000000000..b4bde27f69
--- /dev/null
+++ b/engines/prince/animation.cpp
@@ -0,0 +1,178 @@
+/* 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 "prince/animation.h"
+#include "prince/decompress.h"
+
+#include "common/debug.h"
+#include "common/endian.h"
+
+namespace Prince {
+
+Animation::Animation() : _loopCount(0), _phaseCount(0), _frameCount(0), _baseX(0), _baseY(0)
+{
+}
+
+Animation::~Animation() {
+ clear();
+}
+
+void Animation::clear() {
+ _phaseList.clear();
+ for (int i = 0; i < _frameCount; i++) {
+ _frameList[i]._surface->free();
+ delete _frameList[i]._surface;
+ _frameList[i]._surface = nullptr;
+ if (_frameList[i]._compressedData != nullptr) {
+ free(_frameList[i]._compressedData);
+ _frameList[i]._compressedData = nullptr;
+ }
+ }
+}
+
+bool Animation::loadStream(Common::SeekableReadStream &stream) {
+ stream.skip(2); // skip not used x and y coord diff
+ _loopCount = stream.readUint16LE();
+ _phaseCount = stream.readUint16LE();
+ stream.skip(2); // skip _frameCount here
+ _baseX = stream.readUint16LE();
+ _baseY = stream.readUint16LE();
+ uint32 phaseTableOffset = stream.readUint32LE();
+ uint32 tableOfFrameOffsets = stream.pos();
+
+ stream.seek(phaseTableOffset);
+ Phase tempPhase;
+ _frameCount = 0;
+ for (int phase = 0; phase < _phaseCount; phase++) {
+ tempPhase._phaseOffsetX = stream.readSint16LE();
+ tempPhase._phaseOffsetY = stream.readSint16LE();
+ tempPhase._phaseToFrameIndex = stream.readUint16LE();
+ if (tempPhase._phaseToFrameIndex > _frameCount) {
+ _frameCount = tempPhase._phaseToFrameIndex;
+ }
+ _phaseList.push_back(tempPhase);
+ stream.skip(2);
+ }
+ if (_phaseCount) {
+ _frameCount++;
+ }
+
+ Frame tempFrame;
+ for (int frame = 0; frame < _frameCount; frame++) {
+ stream.seek(tableOfFrameOffsets + frame * 4);
+ uint32 frameInfoOffset = stream.readUint32LE();
+ stream.seek(frameInfoOffset);
+ uint16 frameWidth = stream.readUint16LE();
+ uint16 frameHeight = stream.readUint16LE();
+ uint32 frameDataPos = stream.pos();
+ uint32 frameDataOffset = stream.readUint32BE();
+
+ tempFrame._surface = new Graphics::Surface();
+ tempFrame._surface->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8());
+ if (frameDataOffset == MKTAG('m', 'a', 's', 'm')) {
+ tempFrame._isCompressed = true;
+ tempFrame._dataSize = stream.readUint32LE();
+ tempFrame._compressedData = (byte *)malloc(tempFrame._dataSize);
+ stream.read(tempFrame._compressedData, tempFrame._dataSize);
+ } else {
+ tempFrame._isCompressed = false;
+ tempFrame._dataSize = 0;
+ tempFrame._compressedData = nullptr;
+ stream.seek(frameDataPos);
+ for (uint16 i = 0; i < frameHeight; i++) {
+ stream.read(tempFrame._surface->getBasePtr(0, i), frameWidth);
+ }
+ }
+ _frameList.push_back(tempFrame);
+ }
+
+ return true;
+}
+
+int16 Animation::getLoopCount() const {
+ return _loopCount;
+}
+
+int32 Animation::getPhaseCount() const {
+ return _phaseCount;
+}
+
+int32 Animation::getFrameCount() const {
+ return _frameCount;
+}
+
+int16 Animation::getBaseX() const {
+ return _baseX;
+}
+
+int16 Animation::getBaseY() const {
+ return _baseY;
+}
+
+int16 Animation::getPhaseOffsetX(int phaseIndex) const {
+ if (phaseIndex < _phaseCount) {
+ return _phaseList[phaseIndex]._phaseOffsetX;
+ } else {
+ error("getPhaseOffsetX() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
+ }
+}
+
+int16 Animation::getPhaseOffsetY(int phaseIndex) const {
+ if (phaseIndex < _phaseCount) {
+ return _phaseList[phaseIndex]._phaseOffsetY;
+ } else {
+ error("getPhaseOffsetY() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
+ }
+}
+
+int16 Animation::getPhaseFrameIndex(int phaseIndex) const {
+ if (phaseIndex < _phaseCount) {
+ return _phaseList[phaseIndex]._phaseToFrameIndex;
+ } else {
+ error("getPhaseFrameIndex() phaseIndex: %d, phaseCount: %d", phaseIndex, _phaseCount);
+ }
+}
+
+Graphics::Surface *Animation::getFrame(int frameIndex) {
+ if (frameIndex < _frameCount) {
+ if (_frameList[frameIndex]._isCompressed) {
+ Decompressor dec;
+ byte *ddata = (byte *)malloc(_frameList[frameIndex]._dataSize);
+ dec.decompress(_frameList[frameIndex]._compressedData, ddata, _frameList[frameIndex]._dataSize);
+ int frameHeight = _frameList[frameIndex]._surface->h;
+ int frameWidth = _frameList[frameIndex]._surface->w;
+ for (uint16 i = 0; i < frameHeight; i++) {
+ memcpy(_frameList[frameIndex]._surface->getBasePtr(0, i), ddata + frameWidth * i, frameWidth);
+ }
+ free(ddata);
+ free(_frameList[frameIndex]._compressedData);
+ _frameList[frameIndex]._compressedData = nullptr;
+ _frameList[frameIndex]._dataSize = 0;
+ _frameList[frameIndex]._isCompressed = false;
+ }
+ return _frameList[frameIndex]._surface;
+ } else {
+ error("getFrame() frameIndex: %d, frameCount: %d", frameIndex, _frameCount);
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/animation.h b/engines/prince/animation.h
new file mode 100644
index 0000000000..733acb399c
--- /dev/null
+++ b/engines/prince/animation.h
@@ -0,0 +1,73 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_ANIMATION_H
+#define PRINCE_ANIMATION_H
+
+#include "common/array.h"
+#include "common/stream.h"
+
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class Animation {
+public:
+ Animation();
+ ~Animation();
+ bool loadStream(Common::SeekableReadStream &stream);
+
+ int16 getLoopCount() const;
+ int32 getPhaseCount() const;
+ int32 getFrameCount() const;
+ int16 getBaseX() const;
+ int16 getBaseY() const;
+ int16 getPhaseOffsetX(int phaseIndex) const;
+ int16 getPhaseOffsetY(int phaseIndex) const;
+ int16 getPhaseFrameIndex(int phaseIndex) const;
+ Graphics::Surface *getFrame(int frameIndex);
+ void clear();
+
+private:
+ struct Phase {
+ int16 _phaseOffsetX;
+ int16 _phaseOffsetY;
+ uint16 _phaseToFrameIndex;
+ };
+ struct Frame {
+ bool _isCompressed;
+ uint32 _dataSize;
+ byte *_compressedData;
+ Graphics::Surface *_surface;
+ };
+ Common::Array<Frame> _frameList;
+ Common::Array<Phase> _phaseList;
+ int16 _loopCount;
+ int16 _phaseCount;
+ int32 _frameCount;
+ int16 _baseX;
+ int16 _baseY;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/archive.cpp b/engines/prince/archive.cpp
new file mode 100644
index 0000000000..ae6a2b7546
--- /dev/null
+++ b/engines/prince/archive.cpp
@@ -0,0 +1,144 @@
+/* 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 "prince/archive.h"
+#include "prince/decompress.h"
+
+#include "common/stream.h"
+#include "common/debug.h"
+#include "common/memstream.h"
+
+namespace Prince {
+
+PtcArchive::PtcArchive() : _stream(nullptr) {
+}
+
+PtcArchive::~PtcArchive() {
+ close();
+}
+
+static void decrypt(byte *buffer, uint32 size) {
+ uint32 key = 0xDEADF00D;
+ while (size--) {
+ *buffer++ += key & 0xFF;
+ key ^= 0x2E84299A;
+ key += MKTAG('B', 'L', 'A', 'H');
+ key = ((key & 1) << 31) | (key >> 1);
+ }
+}
+
+bool PtcArchive::open(const Common::String &filename) {
+ _stream = SearchMan.createReadStreamForMember(filename);
+ if (!_stream)
+ return false;
+
+ _stream->readUint32LE(); // magic
+ uint32 fileTableOffset = _stream->readUint32LE() ^ 0x4D4F4B2D; // MOK-
+ uint32 fileTableSize = _stream->readUint32LE() ^ 0x534F4654; // SOFT
+
+ //debug("fileTableOffset : %08X", fileTableOffset);
+ //debug("fileTableSize: %08X", fileTableSize);
+
+ _stream->seek(fileTableOffset);
+
+ byte *fileTable = (byte *)malloc(fileTableSize);
+ byte *fileTableEnd = fileTable + fileTableSize;
+ _stream->read(fileTable, fileTableSize);
+ decrypt(fileTable, fileTableSize);
+
+ for (byte *fileItem = fileTable; fileItem < fileTableEnd; fileItem += 32) {
+ FileEntry item;
+ Common::String name = (const char*)fileItem;
+ item._offset = READ_LE_UINT32(fileItem + 24);
+ item._size = READ_LE_UINT32(fileItem + 28);
+ //debug("%12s %8X %d", name.c_str(), item._offset, item._size);
+ _items[name] = item;
+ }
+
+ free(fileTable);
+
+ return true;
+}
+
+void PtcArchive::close() {
+ delete _stream;
+ _stream = nullptr;
+ _items.clear();
+}
+
+bool PtcArchive::hasFile(const Common::String &name) const {
+ // TODO: check if path matching should be added
+ return _items.contains(name);
+}
+
+int PtcArchive::listMembers(Common::ArchiveMemberList &list) const {
+ int matches = 0;
+
+ for (FileMap::const_iterator it = _items.begin(); it != _items.end(); ++it) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(it->_key, this)));
+ matches++;
+ }
+
+ return matches;
+}
+
+const Common::ArchiveMemberPtr PtcArchive::getMember(const Common::String &name) const {
+ if (!_items.contains(name)) {
+ Common::ArchiveMemberPtr();
+ }
+ return Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *PtcArchive::createReadStreamForMember(const Common::String &name) const {
+ if (!_items.contains(name)) {
+ return 0;
+ }
+
+ const FileEntry &entryHeader = _items[name];
+
+ if (entryHeader._size < 4)
+ return 0;
+
+ uint32 size = entryHeader._size;
+
+ _stream->seek(entryHeader._offset);
+
+ // This *HAS* to be malloc (not new[]) because MemoryReadStream uses free() to free the memory
+ byte *buffer = (byte *)malloc(size);
+ _stream->read(buffer, size);
+
+ if (READ_BE_UINT32(buffer) == MKTAG('M', 'A', 'S', 'M')) {
+ Decompressor dec;
+ uint32 decompLen = READ_BE_UINT32(buffer + 14);
+ byte *decompData = (byte *)malloc(decompLen);
+ dec.decompress(buffer + 18, decompData, decompLen);
+ free(buffer);
+ size = decompLen;
+ buffer = decompData;
+ }
+
+ //debug("PtcArchive::createReadStreamForMember name %s", name.c_str());
+
+ return new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES);
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/archive.h b/engines/prince/archive.h
new file mode 100644
index 0000000000..e211036ed6
--- /dev/null
+++ b/engines/prince/archive.h
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_ARCHIVE_H
+#define PRINCE_ARCHIVE_H
+
+#include "common/archive.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace Prince {
+
+class PtcArchive : public Common::Archive {
+public:
+ PtcArchive();
+ ~PtcArchive();
+
+ bool open(const Common::String &filename);
+ void close();
+ bool isOpen() const { return _stream != 0; }
+
+ // Common::Archive API implementation
+ bool hasFile(const Common::String &name) const;
+ int listMembers(Common::ArchiveMemberList &list) const;
+ const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+ Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+
+private:
+ struct FileEntry {
+ uint32 _offset;
+ uint32 _size;
+ };
+
+ Common::SeekableReadStream *_stream;
+
+ typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+ FileMap _items;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/common.h b/engines/prince/common.h
new file mode 100644
index 0000000000..c846f9a751
--- /dev/null
+++ b/engines/prince/common.h
@@ -0,0 +1,45 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_COMMON_H
+#define PRINCE_COMMON_H
+
+namespace Prince {
+
+enum Direction {
+ kDirLD,
+ kDirL,
+ kDirLU,
+ kDirRD,
+ kDirR,
+ kDirRU,
+ kDirUL,
+ kDirU,
+ kDirUR,
+ kDirDL,
+ kDirD,
+ kDirDR
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/configure.engine b/engines/prince/configure.engine
new file mode 100644
index 0000000000..50740d9f41
--- /dev/null
+++ b/engines/prince/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine prince "The Prince and The Coward" no
diff --git a/engines/prince/cursor.cpp b/engines/prince/cursor.cpp
new file mode 100644
index 0000000000..ddcabbd28f
--- /dev/null
+++ b/engines/prince/cursor.cpp
@@ -0,0 +1,54 @@
+/* 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 "prince/cursor.h"
+
+#include "common/debug.h"
+
+namespace Prince {
+
+Cursor::Cursor() : _surface(nullptr) {
+}
+
+Cursor::~Cursor() {
+ if (_surface != nullptr) {
+ _surface->free();
+ delete _surface;
+ _surface = nullptr;
+ }
+}
+
+bool Cursor::loadStream(Common::SeekableReadStream &stream) {
+ stream.skip(4);
+ uint16 width = stream.readUint16LE();
+ uint16 height = stream.readUint16LE();
+
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int h = 0; h < height; h++) {
+ stream.read(_surface->getBasePtr(0, h), width);
+ }
+ return true;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/cursor.h b/engines/prince/cursor.h
new file mode 100644
index 0000000000..9387f344dc
--- /dev/null
+++ b/engines/prince/cursor.h
@@ -0,0 +1,46 @@
+/* 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.
+ *
+ */
+
+#ifndef CURSOR_PRINCE_H
+#define CURSOR_PRINCE_H
+
+#include "graphics/surface.h"
+
+#include "common/stream.h"
+
+namespace Prince {
+
+class Cursor {
+public:
+ Cursor();
+ ~Cursor();
+
+ bool loadStream(Common::SeekableReadStream &stream);
+ const Graphics::Surface *getSurface() const { return _surface; }
+
+private:
+ Graphics::Surface *_surface;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/curve_values.h b/engines/prince/curve_values.h
new file mode 100644
index 0000000000..d72f11fd36
--- /dev/null
+++ b/engines/prince/curve_values.h
@@ -0,0 +1,45 @@
+/* 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.
+ *
+ */
+
+namespace Prince {
+
+const int curveValues[17][4] = {
+ { 32768, 0, 0, 0 },
+ { 25200, 7200, 480, -112 },
+ { 18816, 12544, 1792, -384 },
+ { 13520, 16224, 3744, -720 },
+ { 9216, 18432, 6144, -1024 },
+ { 5808, 19360, 8800, -1200 },
+ { 3200, 19200, 11520, -1152 },
+ { 1296, 18144, 14112, -784 },
+ { 0, 16384, 16384, 0 },
+ { -784, 14112, 18144, 1296 },
+ { -1152, 11520, 19200, 3200 },
+ { -1200, 8800, 19360, 5808 },
+ { -1024, 6144, 18432, 9216 },
+ { -720, 3744, 16224, 13520 },
+ { -384, 1792, 12544, 18816 },
+ { -112, 480, 7200, 25200 },
+ { 0, 0, 0, 32768 }
+};
+
+} // End of namespace Prince
diff --git a/engines/prince/debugger.cpp b/engines/prince/debugger.cpp
new file mode 100644
index 0000000000..fc216e0cfb
--- /dev/null
+++ b/engines/prince/debugger.cpp
@@ -0,0 +1,174 @@
+/* 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 "prince/debugger.h"
+#include "prince/prince.h"
+#include "prince/flags.h"
+#include "prince/script.h"
+
+namespace Prince {
+
+Debugger::Debugger(PrinceEngine *vm, InterpreterFlags *flags) : GUI::Debugger(), _vm(vm), _locationNr(0), _flags(flags) {
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("level", WRAP_METHOD(Debugger, Cmd_DebugLevel));
+ registerCmd("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag));
+ registerCmd("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag));
+ registerCmd("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag));
+ registerCmd("viewflc", WRAP_METHOD(Debugger, Cmd_ViewFlc));
+ registerCmd("initroom", WRAP_METHOD(Debugger, Cmd_InitRoom));
+ registerCmd("changecursor", WRAP_METHOD(Debugger, Cmd_ChangeCursor));
+ registerCmd("additem", WRAP_METHOD(Debugger, Cmd_AddItem));
+}
+
+static int strToInt(const char *s) {
+ if (!*s)
+ // No string at all
+ return 0;
+ else if (toupper(s[strlen(s) - 1]) != 'H')
+ // Standard decimal string
+ return atoi(s);
+
+ // Hexadecimal string
+ uint tmp = 0;
+ int read = sscanf(s, "%xh", &tmp);
+ if (read < 1)
+ error("strToInt failed on string \"%s\"", s);
+ return (int)tmp;
+}
+
+bool Debugger::Cmd_DebugLevel(int argc, const char **argv) {
+ if (argc == 1) {
+ debugPrintf("Debugging is currently set at level %d\n", gDebugLevel);
+ } else { // set level
+ gDebugLevel = atoi(argv[1]);
+ if (0 <= gDebugLevel && gDebugLevel < 11) {
+ debugPrintf("Debug level set to level %d\n", gDebugLevel);
+ } else if (gDebugLevel < 0) {
+ debugPrintf("Debugging is now disabled\n");
+ } else
+ debugPrintf("Not a valid debug level (0 - 10)\n");
+ }
+
+ return true;
+}
+
+/*
+ * This command sets a flag
+ */
+bool Debugger::Cmd_SetFlag(int argc, const char **argv) {
+ // Check for a flag to set
+ if (argc != 3) {
+ debugPrintf("Usage: %s <flag number> <value>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ uint16 value = strToInt(argv[2]);
+ _flags->setFlagValue((Flags::Id)flagNum, value);
+ return true;
+}
+
+/*
+ * This command gets the value of a flag
+ */
+bool Debugger::Cmd_GetFlag(int argc, const char **argv) {
+ // Check for an flag to display
+ if (argc != 2) {
+ debugPrintf("Usage: %s <flag number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ debugPrintf("Value: %d\n", _flags->getFlagValue((Flags::Id)flagNum));
+ return true;
+}
+
+/*
+ * This command clears a flag
+ */
+bool Debugger::Cmd_ClearFlag(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ debugPrintf("Usage: %s <flag number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ _flags->setFlagValue((Flags::Id)flagNum, 0);
+ return true;
+}
+
+/*
+ * This command starts new flc anim
+ */
+bool Debugger::Cmd_ViewFlc(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ debugPrintf("Usage: %s <anim number>\n", argv[0]);
+ return true;
+ }
+
+ int flagNum = strToInt(argv[1]);
+ _vm->loadAnim(flagNum, false);
+ return true;
+}
+
+bool Debugger::Cmd_InitRoom(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ debugPrintf("Usage: %s <anim number>\n", argv[0]);
+ return true;
+ }
+
+ _locationNr = strToInt(argv[1]);
+ return true;
+}
+
+bool Debugger::Cmd_ChangeCursor(int argc, const char **argv) {
+ // Check for a flag to clear
+ if (argc != 2) {
+ debugPrintf("Usage: %s <curId>\n", argv[0]);
+ return true;
+ }
+
+ _cursorNr = strToInt(argv[1]);
+
+ return true;
+}
+
+bool Debugger::Cmd_AddItem(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Usage: %s <itemId>\n", argv[0]);
+ return true;
+ }
+ if (!strcmp(argv[1], "map")) {
+ _vm->addInv(0, 29, true);
+ _vm->_flags->setFlagValue(Flags::MapaUsable, 1);
+ } else {
+ int itemId = strToInt(argv[1]);
+ _vm->addInv(0, itemId, true);
+ }
+
+ return true;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/debugger.h b/engines/prince/debugger.h
new file mode 100644
index 0000000000..a4467e63d5
--- /dev/null
+++ b/engines/prince/debugger.h
@@ -0,0 +1,58 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_DEBUGGER_H
+#define PRINCE_DEBUGGER_H
+
+#include "common/scummsys.h"
+#include "gui/debugger.h"
+
+namespace Prince {
+
+class PrinceEngine;
+class InterpreterFlags;
+
+class Debugger : public GUI::Debugger {
+public:
+ Debugger(PrinceEngine *vm, InterpreterFlags *flags);
+ virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ
+
+ uint8 _locationNr;
+ uint8 _cursorNr;
+
+private:
+ bool Cmd_DebugLevel(int argc, const char **argv);
+ bool Cmd_SetFlag(int argc, const char **argv);
+ bool Cmd_GetFlag(int argc, const char **argv);
+ bool Cmd_ClearFlag(int argc, const char **argv);
+ bool Cmd_ViewFlc(int argc, const char **argv);
+ bool Cmd_InitRoom(int argc, const char **argv);
+ bool Cmd_ChangeCursor(int argc, const char **argv);
+ bool Cmd_AddItem(int argc, const char **argv);
+
+ PrinceEngine *_vm;
+ InterpreterFlags *_flags;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/decompress.cpp b/engines/prince/decompress.cpp
new file mode 100644
index 0000000000..7fba179541
--- /dev/null
+++ b/engines/prince/decompress.cpp
@@ -0,0 +1,171 @@
+/* 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.
+ *
+ */
+
+// John_Doe's implementation
+
+#include "prince/decompress.h"
+
+namespace Prince {
+
+static const uint16 table1[] = {
+ 0x8000, 0x0002,
+ 0x4000, 0x0004,
+ 0x2000, 0x0008,
+ 0x1000, 0x0010,
+ 0x0800, 0x0020,
+ 0x0400, 0x0040,
+ 0x0200, 0x0080,
+ 0x0100, 0x0100,
+ 0x0080, 0x0200,
+ 0x0040, 0x0400
+};
+
+static const uint32 table2[] = {
+ 0x0000F000,
+ 0x0020FC00,
+ 0x00A0FF00,
+ 0x02A0FF80,
+ 0x06A0FFC0,
+ 0x0EA0FFE0,
+ 0x1EA0FFF0,
+ 0x3EA0FFF8
+};
+
+static const uint16 table3[] = {
+ 0x8000, 0x0000,
+ 0x4000, 0x0002,
+ 0x2000, 0x0006,
+ 0x1000, 0x000E,
+ 0x0800, 0x001E,
+ 0x0400, 0x003E,
+ 0x0200, 0x007E,
+ 0x0100, 0x00FE,
+ 0x0080, 0x01FE,
+ 0x0040, 0x03FE,
+ 0x0020, 0x07FE,
+ 0x0010, 0x0FFE,
+ 0x0008, 0x1FFE,
+ 0x0004, 0x3FFE,
+ 0x0002, 0x7FFE,
+ 0x0001, 0xFFFE
+};
+
+void Decompressor::decompress(byte *source, byte *dest, uint32 destSize) {
+ byte *destEnd = dest + destSize;
+ int more;
+ _src = source;
+ _dst = dest;
+ _bitBuffer = 0x80;
+ while (_dst < destEnd) {
+ uint32 ebp;
+ uint16 offset, length;
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ uint32 tableIndex = 0;
+ while (getBit())
+ tableIndex++;
+ length = table3[tableIndex * 2 + 0];
+ do {
+ more = !(length & 0x8000);
+ length = (length << 1) | getBit();
+ } while (more);
+ length += table3[tableIndex * 2 + 1];
+ length++;
+ memcpy(_dst, _src, length);
+ _src += length;
+ _dst += length;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ if (!getBit()) {
+ if (getBit()) {
+ uint32 tableIndex = getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ ebp = table2[tableIndex];
+ length = 1;
+ } else {
+ ebp = 0x0000FF00;
+ length = 0;
+ }
+ } else {
+ uint32 tableIndex = 0;
+ while (getBit())
+ tableIndex++;
+ length = table1[tableIndex * 2 + 0];
+ do {
+ more = !(length & 0x8000);
+ length = (length << 1) | getBit();
+ } while (more);
+ length += table1[tableIndex * 2 + 1];
+ tableIndex = getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ ebp = table2[tableIndex];
+ }
+ offset = ebp & 0xFFFF;
+ do {
+ if (_bitBuffer == 0x80) {
+ if (offset >= 0xFF00) {
+ offset = (offset << 8) | *_src++;
+ }
+ }
+ more = offset & 0x8000;
+ offset = (offset << 1) | getBit();
+ } while (more);
+ offset += (ebp >> 16);
+ length += 2;
+ while (length--) {
+ if (_dst >= destEnd) {
+ return;
+ }
+ *_dst = *(_dst - offset);
+ _dst++;
+ }
+ }
+}
+
+int Decompressor::getBit() {
+ int bit = (_bitBuffer & 0x80) >> 7;
+ _bitBuffer <<= 1;
+ if (_bitBuffer == 0) {
+ _bitBuffer = *_src++;
+ bit = (_bitBuffer & 0x80) >> 7;
+ _bitBuffer <<= 1;
+ _bitBuffer |= 1;
+ }
+ return bit;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/decompress.h b/engines/prince/decompress.h
new file mode 100644
index 0000000000..ef495db65e
--- /dev/null
+++ b/engines/prince/decompress.h
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+// John_Doe's implementation
+
+#ifndef PRINCE_DECOMPRESS_H
+#define PRINCE_DECOMPRESS_H
+
+#include "engines/util.h"
+
+namespace Prince {
+
+class Decompressor {
+public:
+ void decompress(byte *source, byte *dest, uint32 destSize);
+protected:
+ byte *_src, *_dst;
+ byte _bitBuffer;
+ int _bitsLeft;
+ int getBit();
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/detection.cpp b/engines/prince/detection.cpp
new file mode 100644
index 0000000000..3f83009de8
--- /dev/null
+++ b/engines/prince/detection.cpp
@@ -0,0 +1,73 @@
+/* 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 "prince/detection.h"
+
+namespace Prince {
+
+int PrinceEngine::getGameType() const {
+ return _gameDescription->gameType;
+}
+
+const char *PrinceEngine::getGameId() const {
+ return _gameDescription->desc.gameid;
+}
+
+uint32 PrinceEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+Common::Language PrinceEngine::getLanguage() const {
+ return _gameDescription->desc.language;
+}
+
+bool PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ using namespace Prince;
+ const PrinceGameDescription *gd = (const PrinceGameDescription *)desc;
+ if (gd) {
+ *engine = new PrinceEngine(syst, gd);
+ }
+ return gd != 0;
+}
+
+bool PrinceMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSupportsListSaves);
+}
+
+bool Prince::PrinceEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+} // End of namespace Prince
+
+#if PLUGIN_ENABLED_DYNAMIC(PRINCE)
+REGISTER_PLUGIN_DYNAMIC(PRINCE, PLUGIN_TYPE_ENGINE, Prince::PrinceMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(PRINCE, PLUGIN_TYPE_ENGINE, Prince::PrinceMetaEngine);
+#endif
diff --git a/engines/prince/detection.h b/engines/prince/detection.h
new file mode 100644
index 0000000000..5cc0d32be4
--- /dev/null
+++ b/engines/prince/detection.h
@@ -0,0 +1,100 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_DETECTION_H
+#define PRINCE_DETECTION_H
+
+#include "prince/prince.h"
+#include "engines/advancedDetector.h"
+
+namespace Prince {
+
+struct PrinceGameDescription {
+ ADGameDescription desc;
+ int gameType;
+};
+
+static const PlainGameDescriptor princeGames[] = {
+ {"prince", "Prince Game"},
+ {0, 0}
+};
+
+static const PrinceGameDescription gameDescriptions[] = {
+ {
+ {
+ "prince",
+ "Galador",
+ AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_TESTING,
+ GUIO1(GUIO_NONE)
+ },
+ 0
+ },
+ {
+ {
+ "prince",
+ "Ksiaze i Tchorz",
+ AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
+ Common::PL_POL,
+ Common::kPlatformWindows,
+ ADGF_TESTING,
+ GUIO1(GUIO_NONE)
+ },
+ 1
+ },
+ { AD_TABLE_END_MARKER, 0 }
+};
+
+const static char *directoryGlobs[] = {
+ "all",
+ 0
+};
+
+class PrinceMetaEngine : public AdvancedMetaEngine {
+public:
+ PrinceMetaEngine() : AdvancedMetaEngine(Prince::gameDescriptions, sizeof(Prince::PrinceGameDescription), princeGames) {
+ _singleid = "prince";
+ _maxScanDepth = 2;
+ _directoryGlobs = directoryGlobs;
+ }
+
+ virtual const char *getName() const {
+ return "Prince Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "The Prince and the Coward (C) 1996-97 Metropolis";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual SaveStateList listSaves(const char *target) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+ virtual void removeSaveState(const char *target, int slot) const;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/flags.cpp b/engines/prince/flags.cpp
new file mode 100644
index 0000000000..f1a05bd4df
--- /dev/null
+++ b/engines/prince/flags.cpp
@@ -0,0 +1,420 @@
+/* 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 "prince/flags.h"
+#include "prince/script.h"
+
+namespace Prince {
+
+const char *Flags::getFlagName(uint16 flagId) {
+ FlagDebug *flagd = nullptr;
+ flagd = (FlagDebug *)bsearch(&flagId, _flagNames, kFlagDebugAmount, sizeof(FlagDebug), Flags::compareFlagDebug);
+ if (flagd != nullptr) {
+ return flagd->flagName;
+ } else {
+ return "unknown_flag";
+ }
+}
+
+int Flags::compareFlagDebug(const void *a, const void *b) {
+ const uint32 *flagId = (const uint32 *)a;
+ const FlagDebug *entry = (const FlagDebug *)b;
+ if (*flagId < (uint32)entry->id) {
+ return -1;
+ } else if (*flagId > (uint32)entry->id) {
+ return 1;
+ }
+ return 0;
+}
+
+const Flags::FlagDebug Flags::_flagNames[Flags::kFlagDebugAmount] = {
+ { Flags::FLAGA1, "FLAGA1" },
+ { Flags::FLAGA2, "FLAGA2" },
+ { Flags::FLAGA3, "FLAGA3" },
+ { Flags::DESTX, "DESTX" },
+ { Flags::DESTY, "DESTY" },
+ { Flags::DESTD, "DESTD" },
+ { Flags::DwarfDone, "DwarfDone" },
+ { Flags::GRABARZCOUNTER, "GRABARZCOUNTER" },
+ { Flags::KIERUNEK, "KIERUNEK" },
+ { Flags::BACKFLAG1, "BACKFLAG1" },
+ { Flags::BACKFLAG2, "BACKFLAG2" },
+ { Flags::BACKFLAG3, "BACKFLAG3" },
+ { Flags::BACKFLAG4, "BACKFLAG4" },
+ { Flags::MACROFLAG1, "MACROFLAG1" },
+ { Flags::MACROFLAG2, "MACROFLAG2" },
+ { Flags::MACROFLAG3, "MACROFLAG3" },
+ { Flags::HEROLDDONE, "HEROLDDONE" },
+ { Flags::BRIDGESET, "BRIDGESET" },
+ { Flags::U_BT_1, "U_BT_1" },
+ { Flags::U_BT_2, "U_BT_2" },
+ { Flags::U_BT_3, "U_BT_3" },
+ { Flags::U_BT_4, "U_BT_4" },
+ { Flags::U_BT_5, "U_BT_5" },
+ { Flags::U_BT_6, "U_BT_6" },
+ { Flags::U_BT_7, "U_BT_7" },
+ { Flags::U_BT_8, "U_BT_8" },
+ { Flags::U_BT_9, "U_BT_9" },
+ { Flags::U_BT_COUNTER, "U_BT_COUNTER" },
+ { Flags::ARIVALDALIVE, "ARIVALDALIVE" },
+ { Flags::TALKCHAR1, "TALKCHAR1" },
+ { Flags::TalkType1, "TalkType1" },
+ { Flags::TALKROUT1, "TALKROUT1" },
+ { Flags::TALKROUT2, "TALKROUT2" },
+ { Flags::TALKROUT3, "TALKROUT3" },
+ { Flags::TALKROUT4, "TALKROUT4" },
+ { Flags::TALKANIM1, "TALKANIM1" },
+ { Flags::TALKANIM2, "TALKANIM2" },
+ { Flags::TALKCOLOR1, "TALKCOLOR1" },
+ { Flags::TALKCOLOR2, "TALKCOLOR2" },
+ { Flags::KapciuchTaken, "KapciuchTaken" },
+ { Flags::CurrentBeggarA, "CurrentBeggarA" },
+ { Flags::TempKapc, "TempKapc" },
+ { Flags::HomTaken, "HomTaken" },
+ { Flags::WizardTalk, "WizardTalk" },
+ { Flags::SunlordTalk, "SunlordTalk" },
+ { Flags::HermitTalk, "HermitTalk" },
+ { Flags::RunyMode, "RunyMode" },
+ { Flags::FatMerchantTalk, "FatMerchantTalk" },
+ { Flags::HotDogTalk, "HotDogTalk" },
+ { Flags::ThiefTalk, "ThiefTalk" },
+ { Flags::BeggarTalk, "BeggarTalk" },
+ { Flags::MonkTalk, "MonkTalk" },
+ { Flags::BardTalk, "BardTalk" },
+ { Flags::BarmanTalk, "BarmanTalk" },
+ { Flags::LeftPlayerTalk, "LeftPlayerTalk" },
+ { Flags::OczySowy, "OczySowy" },
+ { Flags::CzachySpeed1, "CzachySpeed1" },
+ { Flags::CzachySpeed2, "CzachySpeed2" },
+ { Flags::CzachySpeed3, "CzachySpeed3" },
+ { Flags::CzachySlowDown1, "CzachySlowDown1" },
+ { Flags::CzachySlowDown2, "CzachySlowDown2" },
+ { Flags::CzachySlowDown3, "CzachySlowDown3" },
+ { Flags::FjordDane, "FjordDane" },
+ { Flags::GKopany1, "GKopany1" },
+ { Flags::GKopany2, "GKopany2" },
+ { Flags::GKopany3, "GKopany3" },
+ { Flags::GKopany4, "GKopany4" },
+ { Flags::KnowGodWord, "KnowGodWord" },
+ { Flags::TALKROUT21, "TALKROUT21" },
+ { Flags::TALKROUT22, "TALKROUT22" },
+ { Flags::TALKROUT23, "TALKROUT23" },
+ { Flags::TALKROUT24, "TALKROUT24" },
+ { Flags::TalkType2, "TalkType2" },
+ { Flags::GrabarzTalk, "GrabarzTalk" },
+ { Flags::LastTalker, "LastTalker" },
+ { Flags::MapaPustelniaEnabled, "MapaPustelniaEnabled" },
+ { Flags::MapaTempleEnabled, "MapaTempleEnabled" },
+ { Flags::MapaFjordEnabled, "MapaFjordEnabled" },
+ { Flags::MapaSilmanionaEnabled, "MapaSilmanionaEnabled" },
+ { Flags::MapaKurhanEnabled, "MapaKurhanEnabled" },
+ { Flags::MapaDragonEnabled, "MapaDragonEnabled" },
+ { Flags::MapaMillEnabled, "MapaMillEnabled" },
+ { Flags::DwarfRunning, "DwarfRunning" },
+ { Flags::DwarfTalk, "DwarfTalk" },
+ { Flags::CurseLift, "CurseLift" },
+ { Flags::KosciSwapped, "KosciSwapped" },
+ { Flags::BookStolen, "BookStolen" },
+ { Flags::MapaUsable, "MapaUsable" },
+ { Flags::FjordBoss, "FjordBoss" },
+ { Flags::FjordHotDog, "FjordHotDog" },
+ { Flags::FjordLewy, "FjordLewy" },
+ { Flags::FjordPrawy, "FjordPrawy" },
+ { Flags::TalkArivald, "TalkArivald" },
+ { Flags::ShootDone, "ShootDone" },
+ { Flags::ShootRunning, "ShootRunning" },
+ { Flags::ShootKnow, "ShootKnow" },
+ { Flags::MirrorKnow, "MirrorKnow" },
+ { Flags::Gar1stTime, "Gar1stTime" },
+ { Flags::KosciTaken, "KosciTaken" },
+ { Flags::ArivGotSpell, "ArivGotSpell" },
+ { Flags::BookGiven, "BookGiven" },
+ { Flags::Wywieszka, "Wywieszka" },
+ { Flags::TalkSheila, "TalkSheila" },
+ { Flags::TalkSheila2, "TalkSheila2" },
+ { Flags::BackHuman, "BackHuman" },
+ { Flags::SkarbiecOpen, "SkarbiecOpen" },
+ { Flags::LustroTaken, "LustroTaken" },
+ { Flags::GargoyleHom, "GargoyleHom" },
+ { Flags::GargoyleBroken, "GargoyleBroken" },
+ { Flags::FjordDzien, "FjordDzien" },
+ { Flags::GargoyleHom2, "GargoyleHom2" },
+ { Flags::RunMonstersRunning, "RunMonstersRunning" },
+ { Flags::FoundPaperInCoffin, "FoundPaperInCoffin" },
+ { Flags::KnowSunlord, "KnowSunlord" },
+ { Flags::KnowSunlordTalk, "KnowSunlordTalk" },
+ { Flags::ArivaldCzyta, "ArivaldCzyta" },
+ { Flags::TelepX, "TelepX" },
+ { Flags::TelepY, "TelepY" },
+ { Flags::TelepDir, "TelepDir" },
+ { Flags::TelepRoom, "TelepRoom" },
+ { Flags::ListStolen, "ListStolen" },
+ { Flags::WifeInDoor, "WifeInDoor" },
+ { Flags::TalkWifeFlag, "TalkWifeFlag" },
+ { Flags::LetterGiven, "LetterGiven" },
+ { Flags::LutniaTaken, "LutniaTaken" },
+ { Flags::BardHomeOpen, "BardHomeOpen" },
+ { Flags::FjordNoMonsters, "FjordNoMonsters" },
+ { Flags::ShandriaWallTalking, "ShandriaWallTalking" },
+ { Flags::ShandriaWallCounter, "ShandriaWallCounter" },
+ { Flags::ShandriaWallDone, "ShandriaWallDone" },
+ { Flags::FutureDone, "FutureDone" },
+ { Flags::TalkButch, "TalkButch" },
+ { Flags::GotSzalik, "GotSzalik" },
+ { Flags::GotCzosnek, "GotCzosnek" },
+ { Flags::BearDone, "BearDone" },
+ { Flags::NekrVisited, "NekrVisited" },
+ { Flags::SunRiddle, "SunRiddle" },
+ { Flags::PtaszekAway, "PtaszekAway" },
+ { Flags::KotGadanie, "KotGadanie" },
+ { Flags::SzlafmycaTaken, "SzlafmycaTaken" },
+ { Flags::BabkaTalk, "BabkaTalk" },
+ { Flags::SellerTalk, "SellerTalk" },
+ { Flags::CzosnekDone, "CzosnekDone" },
+ { Flags::PriestCounter, "PriestCounter" },
+ { Flags::PriestGest1, "PriestGest1" },
+ { Flags::PriestGest2, "PriestGest2" },
+ { Flags::PriestGest3, "PriestGest3" },
+ { Flags::PriestGest4, "PriestGest4" },
+ { Flags::PriestAnim, "PriestAnim" },
+ { Flags::HolyWaterTaken, "HolyWaterTaken" },
+ { Flags::AxeTaken, "AxeTaken" },
+ { Flags::BadylTaken1, "BadylTaken1" },
+ { Flags::BadylTaken2, "BadylTaken2" },
+ { Flags::BadylSharpened, "BadylSharpened" },
+ { Flags::PorwanieSmoka, "PorwanieSmoka" },
+ { Flags::ShopReOpen, "ShopReOpen" },
+ { Flags::LuskaShown, "LuskaShown" },
+ { Flags::CudKnow, "CudKnow" },
+ { Flags::VampireDead, "VampireDead" },
+ { Flags::MapaVisible1, "MapaVisible1" },
+ { Flags::MapaVisible2, "MapaVisible2" },
+ { Flags::MapaVisible3, "MapaVisible3" },
+ { Flags::MapaVisible4, "MapaVisible4" },
+ { Flags::MapaVisible5, "MapaVisible5" },
+ { Flags::MapaVisible6, "MapaVisible6" },
+ { Flags::MapaVisible7, "MapaVisible7" },
+ { Flags::MapaVisible8, "MapaVisible8" },
+ { Flags::MapaVisible9, "MapaVisible9" },
+ { Flags::MapaX, "MapaX" },
+ { Flags::MapaY, "MapaY" },
+ { Flags::MapaD, "MapaD" },
+ { Flags::OldMapaX, "OldMapaX" },
+ { Flags::OldMapaY, "OldMapaY" },
+ { Flags::OldMapaD, "OldMapaD" },
+ { Flags::MovingBack, "MovingBack" },
+ { Flags::MapaCount, "MapaCount" },
+ { Flags::Pustelnia1st, "Pustelnia1st" },
+ { Flags::CzarnePole1st, "CzarnePole1st" },
+ { Flags::TalkArivNum, "TalkArivNum" },
+ { Flags::Pfui, "Pfui" },
+ { Flags::MapaSunlordEnabled, "MapaSunlordEnabled" },
+ { Flags::WebDone, "WebDone" },
+ { Flags::DragonDone, "DragonDone" },
+ { Flags::KanPlay, "KanPlay" },
+ { Flags::OldKanPlay, "OldKanPlay" },
+ { Flags::LapkiWait, "LapkiWait" },
+ { Flags::WebNoCheck, "WebNoCheck" },
+ { Flags::Perfumeria, "Perfumeria" },
+ { Flags::SmokNoCheck, "SmokNoCheck" },
+ { Flags::IluzjaBroken, "IluzjaBroken" },
+ { Flags::IluzjaWorking, "IluzjaWorking" },
+ { Flags::IluzjaCounter, "IluzjaCounter" },
+ { Flags::KurhanOpen1, "KurhanOpen1" },
+ { Flags::KastetTaken, "KastetTaken" },
+ { Flags::KastetDown, "KastetDown" },
+ { Flags::KurhanDone, "KurhanDone" },
+ { Flags::SkelCounter, "SkelCounter" },
+ { Flags::SkelDial1, "SkelDial1" },
+ { Flags::SkelDial2, "SkelDial2" },
+ { Flags::SkelDial3, "SkelDial3" },
+ { Flags::SkelDial4, "SkelDial4" },
+ { Flags::SameTalker, "SameTalker" },
+ { Flags::RunMonstersText, "RunMonstersText" },
+ { Flags::PiwnicaChecked, "PiwnicaChecked" },
+ { Flags::DragonTalked, "DragonTalked" },
+ { Flags::ToldAboutBook, "ToldAboutBook" },
+ { Flags::SilmanionaDone, "SilmanionaDone" },
+ { Flags::ToldBookCount, "ToldBookCount" },
+ { Flags::SmrodNoCheck, "SmrodNoCheck" },
+ { Flags::RopeTaken, "RopeTaken" },
+ { Flags::RopeTime, "RopeTime" },
+ { Flags::LaskaFree, "LaskaFree" },
+ { Flags::ShanSmokTalked, "ShanSmokTalked" },
+ { Flags::SwordTaken, "SwordTaken" },
+ { Flags::Mill1st, "Mill1st" },
+ { Flags::SawRat, "SawRat" },
+ { Flags::KnowRat, "KnowRat" },
+ { Flags::DziuraTimer, "DziuraTimer" },
+ { Flags::LaskaInside, "LaskaInside" },
+ { Flags::HoleBig, "HoleBig" },
+ { Flags::EnableWiedzmin, "EnableWiedzmin" },
+ { Flags::EnableTrucizna, "EnableTrucizna" },
+ { Flags::KnowPoison, "KnowPoison" },
+ { Flags::KufelTaken, "KufelTaken" },
+ { Flags::BojkaEnabled, "BojkaEnabled" },
+ { Flags::BitwaNot1st, "BitwaNot1st" },
+ { Flags::BojkaTimer, "BojkaTimer" },
+ { Flags::BojkaGirl, "BojkaGirl" },
+ { Flags::Look1st, "Look1st" },
+ { Flags::RatTaken, "RatTaken" },
+ { Flags::LaskaTalkedGr, "LaskaTalkedGr" },
+ { Flags::RatusGivus, "RatusGivus" },
+ { Flags::MamObole, "MamObole" },
+ { Flags::Speed1st, "Speed1st" },
+ { Flags::SpeedTimer, "SpeedTimer" },
+ { Flags::ProveIt, "ProveIt" },
+ { Flags::Proven, "Proven" },
+ { Flags::ShowWoalka, "ShowWoalka" },
+ { Flags::PoisonTaken, "PoisonTaken" },
+ { Flags::HellOpened, "HellOpened" },
+ { Flags::HellNoCheck, "HellNoCheck" },
+ { Flags::TalAn1, "TalAn1" },
+ { Flags::TalAn2, "TalAn2" },
+ { Flags::TalAn3, "TalAn3" },
+ { Flags::TalkDevilGuard, "TalkDevilGuard" },
+ { Flags::Sword1st, "Sword1st" },
+ { Flags::IluzjaNoCheck, "IluzjaNoCheck" },
+ { Flags::RozdzielniaNumber, "RozdzielniaNumber" },
+ { Flags::JailChecked, "JailChecked" },
+ { Flags::JailTalked, "JailTalked" },
+ { Flags::TrickFailed, "TrickFailed" },
+ { Flags::WegielVisible, "WegielVisible" },
+ { Flags::WegielTimer1, "WegielTimer1" },
+ { Flags::RandomSample, "RandomSample" },
+ { Flags::RandomSampleTimer, "RandomSampleTimer" },
+ { Flags::SampleTimer, "SampleTimer" },
+ { Flags::ZonaSample, "ZonaSample" },
+ { Flags::HoleTryAgain, "HoleTryAgain" },
+ { Flags::TeleportTimer, "TeleportTimer" },
+ { Flags::RozLezy, "RozLezy" },
+ { Flags::UdkoTimer, "UdkoTimer" },
+ { Flags::ZaworZatkany, "ZaworZatkany" },
+ { Flags::ZaworOpened, "ZaworOpened" },
+ { Flags::DoorExploded, "DoorExploded" },
+ { Flags::SkoraTaken, "SkoraTaken" },
+ { Flags::CiezkieByl, "CiezkieByl" },
+ { Flags::MamWegiel, "MamWegiel" },
+ { Flags::SwiecaAway, "SwiecaAway" },
+ { Flags::ITSAVE, "ITSAVE" },
+ { Flags::RozpadlSie, "RozpadlSie" },
+ { Flags::WegielFullTimer, "WegielFullTimer" },
+ { Flags::WegielDown, "WegielDown" },
+ { Flags::WegielDownTimer, "WegielDownTimer" },
+ { Flags::PaliSie, "PaliSie" },
+ { Flags::DiabGuardTalked, "DiabGuardTalked" },
+ { Flags::GuardsNoCheck, "GuardsNoCheck" },
+ { Flags::TalkedPowloka, "TalkedPowloka" },
+ { Flags::JailOpen, "JailOpen" },
+ { Flags::PrzytulTimer, "PrzytulTimer" },
+ { Flags::JailDone, "JailDone" },
+ { Flags::MamMonety, "MamMonety" },
+ { Flags::LotTimer, "LotTimer" },
+ { Flags::LotObj, "LotObj" },
+ { Flags::PtakTimer, "PtakTimer" },
+ { Flags::BookTimer, "BookTimer" },
+ { Flags::BookGiba, "BookGiba" },
+ { Flags::PtakLata, "PtakLata" },
+ { Flags::Podej, "Podej" },
+ { Flags::GotHint, "GotHint" },
+ { Flags::LawaLeci, "LawaLeci" },
+ { Flags::PowerKlik, "PowerKlik" },
+ { Flags::LucekBad, "LucekBad" },
+ { Flags::LucekBad1st, "LucekBad1st" },
+ { Flags::IntroDial1, "IntroDial1" },
+ { Flags::IntroDial2, "IntroDial2" },
+ { Flags::ItsOutro, "ItsOutro" },
+ { Flags::KamienComment, "KamienComment" },
+ { Flags::KamienSkip, "KamienSkip" },
+ { Flags::TesterFlag, "TesterFlag" },
+ { Flags::RememberLine, "RememberLine" },
+ { Flags::OpisLapek, "OpisLapek" },
+ { Flags::TalWait, "TalWait" },
+ { Flags::OpisKamienia, "OpisKamienia" },
+ { Flags::JumpBox, "JumpBox" },
+ { Flags::JumpBox1, "JumpBox1" },
+ { Flags::JumpBox2, "JumpBox2" },
+ { Flags::JumpBox3, "JumpBox3" },
+ { Flags::SpecPiesek, "SpecPiesek" },
+ { Flags::SpecPiesekCount, "SpecPiesekCount" },
+ { Flags::SpecPiesekGadanie, "SpecPiesekGadanie" },
+ { Flags::ZnikaFlag, "ZnikaFlag" },
+ { Flags::ZnikaTimer, "ZnikaTimer" },
+ { Flags::SowaTimer, "SowaTimer" },
+ { Flags::MamrotanieOff, "MamrotanieOff" },
+ { Flags::CURRMOB, "CURRMOB" },
+ { Flags::KOLOR, "KOLOR" },
+ { Flags::MBFLAG, "MBFLAG" },
+ { Flags::MXFLAG, "MXFLAG" },
+ { Flags::MYFLAG, "MYFLAG" },
+ { Flags::SCROLLTYPE, "SCROLLTYPE" },
+ { Flags::SCROLLVALUE, "SCROLLVALUE" },
+ { Flags::SCROLLVALUE2, "SCROLLVALUE2" },
+ { Flags::TALKEXITCODE, "TALKEXITCODE" },
+ { Flags::SPECROUTFLAG1, "SPECROUTFLAG1" },
+ { Flags::SPECROUTFLAG2, "SPECROUTFLAG2" },
+ { Flags::SPECROUTFLAG3, "SPECROUTFLAG3" },
+ { Flags::TALKFLAGCODE, "TALKFLAGCODE" },
+ { Flags::CURRROOM, "CURRROOM" },
+ { Flags::Talker1Init, "Talker1Init" },
+ { Flags::Talker2Init, "Talker2Init" },
+ { Flags::RESTOREROOM, "RESTOREROOM" },
+ { Flags::INVALLOWED, "INVALLOWED" },
+ { Flags::BOXSEL, "BOXSEL" },
+ { Flags::CURSEBLINK, "CURSEBLINK" },
+ { Flags::EXACTMOVE, "EXACTMOVE" },
+ { Flags::MOVEDESTX, "MOVEDESTX" },
+ { Flags::MOVEDESTY, "MOVEDESTY" },
+ { Flags::NOANTIALIAS, "NOANTIALIAS" },
+ { Flags::ESCAPED, "ESCAPED" },
+ { Flags::ALLOW1OPTION, "ALLOW1OPTION" },
+ { Flags::VOICE_H_LINE, "VOICE_H_LINE" },
+ { Flags::VOICE_A_LINE, "VOICE_A_LINE" },
+ { Flags::VOICE_B_LINE, "VOICE_B_LINE" },
+ { Flags::VOICE_C_LINE, "VOICE_C_LINE" },
+ { Flags::NOHEROATALL, "NOHEROATALL" },
+ { Flags::MOUSEENABLED, "MOUSEENABLED" },
+ { Flags::DIALINES, "DIALINES" },
+ { Flags::SHANWALK, "SHANWALK" },
+ { Flags::SHANDOG, "SHANDOG" },
+ { Flags::GETACTIONBACK, "GETACTIONBACK" },
+ { Flags::GETACTIONDATA, "GETACTIONDATA" },
+ { Flags::GETACTION, "GETACTION" },
+ { Flags::HEROFAST, "HEROFAST" },
+ { Flags::SELITEM, "SELITEM" },
+ { Flags::LMOUSE, "LMOUSE" },
+ { Flags::MINMX, "MINMX" },
+ { Flags::MAXMX, "MAXMX" },
+ { Flags::MINMY, "MINMY" },
+ { Flags::MAXMY, "MAXMY" },
+ { Flags::TORX1, "TORX1" },
+ { Flags::TORY1, "TORY1" },
+ { Flags::TORX2, "TORX2" },
+ { Flags::TORY2, "TORY2" },
+ { Flags::POWER, "POWER" },
+ { Flags::POWERENABLED, "POWERENABLED" },
+ { Flags::FLCRESTORE, "FLCRESTORE" },
+ { Flags::NOCLSTEXT, "NOCLSTEXT" },
+ { Flags::ESCAPED2, "ESCAPED2" },
+};
+
+} // End of namespace Prince
diff --git a/engines/prince/flags.h b/engines/prince/flags.h
new file mode 100644
index 0000000000..8337f82a95
--- /dev/null
+++ b/engines/prince/flags.h
@@ -0,0 +1,421 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_FLAGS_H
+#define PRINCE_FLAGS_H
+
+#include "common/scummsys.h"
+
+namespace Prince {
+
+class Flags {
+public:
+ static int compareFlagDebug(const void *a, const void *b);
+ static const char *getFlagName(uint16 flagId);
+
+ enum Id {
+ FLAGA1 = 0x8000,
+ FLAGA2 = 0x8002,
+ FLAGA3 = 0x8004,
+ DESTX = 0x8006,
+ DESTY = 0x8008,
+ DESTD = 0x800A,
+ DwarfDone = 0x800C,
+ GRABARZCOUNTER = 0x800E,
+ KIERUNEK = 0x8010,
+ BACKFLAG1 = 0x8012,
+ BACKFLAG2 = 0x8014,
+ BACKFLAG3 = 0x8016,
+ BACKFLAG4 = 0x8018,
+ MACROFLAG1 = 0x801A,
+ MACROFLAG2 = 0x801C,
+ MACROFLAG3 = 0x801E,
+ HEROLDDONE = 0x8020,
+ BRIDGESET = 0x8022,
+ U_BT_1 = 0x8024,
+ U_BT_2 = 0x8026,
+ U_BT_3 = 0x8028,
+ U_BT_4 = 0x802A,
+ U_BT_5 = 0x802C,
+ U_BT_6 = 0x802E,
+ U_BT_7 = 0x8030,
+ U_BT_8 = 0x8032,
+ U_BT_9 = 0x8034,
+ U_BT_COUNTER = 0x8036,
+ ARIVALDALIVE = 0x8038,
+ TALKCHAR1 = 0x803A,
+ TalkType1 = 0x803C,
+ TALKROUT1 = 0x803E,
+ TALKROUT2 = 0x8042,
+ TALKROUT3 = 0x8046,
+ TALKROUT4 = 0x804A,
+ TALKANIM1 = 0x804E,
+ TALKANIM2 = 0x8050,
+ TALKCOLOR1 = 0x8052,
+ TALKCOLOR2 = 0x8054,
+ KapciuchTaken = 0x8056,
+ CurrentBeggarA = 0x8058,
+ TempKapc = 0x805A,
+ HomTaken = 0x805C,
+ WizardTalk = 0x805E,
+ SunlordTalk = 0x8060,
+ HermitTalk = 0x8062,
+ RunyMode = 0x8064,
+ FatMerchantTalk = 0x8066,
+ HotDogTalk = 0x8068,
+ ThiefTalk = 0x806A,
+ BeggarTalk = 0x806C,
+ // DwarfTalk = 0x806E, // Redefinition
+ MonkTalk = 0x8070,
+ BardTalk = 0x8072,
+ BarmanTalk = 0x8074,
+ LeftPlayerTalk = 0x8076,
+ OczySowy = 0x8078,
+ CzachySpeed1 = 0x807A,
+ CzachySpeed2 = 0x807C,
+ CzachySpeed3 = 0x807E,
+ CzachySlowDown1 = 0x8080,
+ CzachySlowDown2 = 0x8082,
+ CzachySlowDown3 = 0x8084,
+ FjordDane = 0x8086,
+ GKopany1 = 0x8088,
+ GKopany2 = 0x808A,
+ GKopany3 = 0x808C,
+ GKopany4 = 0x808E,
+ KnowGodWord = 0x8090,
+ TALKROUT21 = 0x8092,
+ TALKROUT22 = 0x8096,
+ TALKROUT23 = 0x809A,
+ TALKROUT24 = 0x809E,
+ TalkType2 = 0x80A2,
+ GrabarzTalk = 0x80A4,
+ LastTalker = 0x80A6,
+ MapaPustelniaEnabled = 0x80A8,
+ MapaTempleEnabled = 0x80AA,
+ MapaFjordEnabled = 0x80AC,
+ MapaSilmanionaEnabled = 0x80AE,
+ MapaKurhanEnabled = 0x80B0,
+ MapaDragonEnabled = 0x80B2,
+ MapaMillEnabled = 0x80B4,
+ DwarfRunning = 0x80B6,
+ DwarfTalk = 0x80B8,
+ CurseLift = 0x80BA,
+ KosciSwapped = 0x80BC,
+ BookStolen = 0x80BE,
+ MapaUsable = 0x80C0,
+ FjordBoss = 0x80C2,
+ FjordHotDog = 0x80C4,
+ FjordLewy = 0x80C6,
+ FjordPrawy = 0x80C8,
+ TalkArivald = 0x80CA,
+ ShootDone = 0x80CC,
+ ShootRunning = 0x80CE,
+ ShootKnow = 0x80D0,
+ MirrorKnow = 0x80D2,
+ Gar1stTime = 0x80D4,
+ KosciTaken = 0x80D6,
+ ArivGotSpell = 0x80D8,
+ BookGiven = 0x80DA,
+ Wywieszka = 0x80DC,
+ TalkSheila = 0x80DE,
+ TalkSheila2 = 0x80E0,
+ BackHuman = 0x80E2,
+ SkarbiecOpen = 0x80E4,
+ LustroTaken = 0x80E6,
+ GargoyleHom = 0x80E8,
+ GargoyleBroken = 0x80EA,
+ FjordDzien = 0x80EC,
+ GargoyleHom2 = 0x80EE,
+ RunMonstersRunning = 0x80F0,
+ FoundPaperInCoffin = 0x80F2,
+ KnowSunlord = 0x80F4,
+ KnowSunlordTalk = 0x80F6,
+ ArivaldCzyta = 0x80F8,
+ TelepX = 0x80FA,
+ TelepY = 0x80FC,
+ TelepDir = 0x80FE,
+ TelepRoom = 0x8100,
+ ListStolen = 0x8102,
+ WifeInDoor = 0x8104,
+ TalkWifeFlag = 0x8106,
+ LetterGiven = 0x8108,
+ LutniaTaken = 0x810A,
+ BardHomeOpen = 0x810C,
+ FjordNoMonsters = 0x810E,
+ ShandriaWallTalking = 0x8110,
+ ShandriaWallCounter = 0x8112,
+ ShandriaWallDone = 0x8114,
+ FutureDone = 0x8116,
+ TalkButch = 0x8118,
+ GotSzalik = 0x811A,
+ GotCzosnek = 0x811C,
+ BearDone = 0x811E,
+ NekrVisited = 0x8120,
+ SunRiddle = 0x8122,
+ PtaszekAway = 0x8124,
+ KotGadanie = 0x8126,
+ SzlafmycaTaken = 0x8128,
+ BabkaTalk = 0x812A,
+ SellerTalk = 0x812C,
+ CzosnekDone = 0x812E,
+ PriestCounter = 0x8130,
+ PriestGest1 = 0x8132,
+ PriestGest2 = 0x8134,
+ PriestGest3 = 0x8136,
+ PriestGest4 = 0x8138,
+ PriestAnim = 0x813A,
+ HolyWaterTaken = 0x813C,
+ AxeTaken = 0x813E,
+ BadylTaken1 = 0x8140,
+ BadylTaken2 = 0x8142,
+ BadylSharpened = 0x8144,
+ PorwanieSmoka = 0x8146,
+ ShopReOpen = 0x8148,
+ LuskaShown = 0x814A,
+ CudKnow = 0x814C,
+ VampireDead = 0x814E,
+ MapaVisible1 = 0x8150,
+ MapaVisible2 = 0x8152,
+ MapaVisible3 = 0x8154,
+ MapaVisible4 = 0x8156,
+ MapaVisible5 = 0x8158,
+ MapaVisible6 = 0x815A,
+ MapaVisible7 = 0x815C,
+ MapaVisible8 = 0x815E,
+ MapaVisible9 = 0x8160,
+ MapaX = 0x8162,
+ MapaY = 0x8164,
+ MapaD = 0x8166,
+ OldMapaX = 0x8168,
+ OldMapaY = 0x816A,
+ OldMapaD = 0x816C,
+ MovingBack = 0x816E,
+ MapaCount = 0x8170,
+ Pustelnia1st = 0x8172,
+ CzarnePole1st = 0x8174,
+ TalkArivNum = 0x8176,
+ Pfui = 0x8178,
+ MapaSunlordEnabled = 0x817A,
+ WebDone = 0x817C,
+ DragonDone = 0x817E,
+ KanPlay = 0x8180,
+ OldKanPlay = 0x8182,
+ LapkiWait = 0x8184,
+ WebNoCheck = 0x8186,
+ Perfumeria = 0x8188,
+ SmokNoCheck = 0x818A,
+ IluzjaBroken = 0x818C,
+ IluzjaWorking = 0x818E,
+ IluzjaCounter = 0x8190,
+ KurhanOpen1 = 0x8192,
+ KastetTaken = 0x8194,
+ KastetDown = 0x8196,
+ KurhanDone = 0x8198,
+ SkelCounter = 0x819A,
+ SkelDial1 = 0x819C,
+ SkelDial2 = 0x819E,
+ SkelDial3 = 0x81A0,
+ SkelDial4 = 0x81A2,
+ SameTalker = 0x81A4,
+ RunMonstersText = 0x81A6,
+ PiwnicaChecked = 0x81A8,
+ DragonTalked = 0x81AA,
+ ToldAboutBook = 0x81AC,
+ SilmanionaDone = 0x81AE,
+ ToldBookCount = 0x81B0,
+ SmrodNoCheck = 0x81B2,
+ RopeTaken = 0x81B4,
+ RopeTime = 0x81B6,
+ LaskaFree = 0x81B8,
+ ShanSmokTalked = 0x81BA,
+ SwordTaken = 0x81BC,
+ Mill1st = 0x81BE,
+ SawRat = 0x81C0,
+ KnowRat = 0x81C2,
+ DziuraTimer = 0x81C4,
+ LaskaInside = 0x81C6,
+ HoleBig = 0x81C8,
+ EnableWiedzmin = 0x81CA,
+ EnableTrucizna = 0x81CC,
+ KnowPoison = 0x81CE,
+ KufelTaken = 0x81D0,
+ BojkaEnabled = 0x81D2,
+ BitwaNot1st = 0x81D4,
+ BojkaTimer = 0x81D6,
+ BojkaGirl = 0x81D8,
+ Look1st = 0x81DA,
+ RatTaken = 0x81DC,
+ LaskaTalkedGr = 0x81DE,
+ RatusGivus = 0x81E0,
+ MamObole = 0x81E2,
+ Speed1st = 0x81E4,
+ SpeedTimer = 0x81E6,
+ ProveIt = 0x81E8,
+ Proven = 0x81EA,
+ ShowWoalka = 0x81EC,
+ PoisonTaken = 0x81EE,
+ HellOpened = 0x81F0,
+ HellNoCheck = 0x81F2,
+ TalAn1 = 0x81F4,
+ TalAn2 = 0x81F6,
+ TalAn3 = 0x81F8,
+ TalkDevilGuard = 0x81fA,
+ Sword1st = 0x81FC,
+ IluzjaNoCheck = 0x81FE,
+ RozdzielniaNumber = 0x8200,
+ JailChecked = 0x8202,
+ JailTalked = 0x8204,
+ TrickFailed = 0x8206,
+ WegielVisible = 0x8208,
+ WegielTimer1 = 0x820A,
+ RandomSample = 0x820C,
+ RandomSampleTimer = 0x820E,
+ SampleTimer = 0x8210,
+ ZonaSample = 0x8212,
+ HoleTryAgain = 0x8214,
+ TeleportTimer = 0x8216,
+ RozLezy = 0x8218,
+ UdkoTimer = 0x821A,
+ ZaworZatkany = 0x821C,
+ ZaworOpened = 0x821E,
+ DoorExploded = 0x8220,
+ SkoraTaken = 0x8222,
+ CiezkieByl = 0x8224,
+ MamWegiel = 0x8226,
+ SwiecaAway = 0x8228,
+ ITSAVE = 0x822A,
+ RozpadlSie = 0x822C,
+ WegielFullTimer = 0x822E,
+ WegielDown = 0x8230,
+ WegielDownTimer = 0x8232,
+ PaliSie = 0x8234,
+ DiabGuardTalked = 0x8236,
+ GuardsNoCheck = 0x8238,
+ TalkedPowloka = 0x823A,
+ JailOpen = 0x823C,
+ PrzytulTimer = 0x823E,
+ JailDone = 0x8240,
+ MamMonety = 0x8242,
+ LotTimer = 0x8244,
+ LotObj = 0x8246,
+ PtakTimer = 0x8248,
+ BookTimer = 0x824A,
+ BookGiba = 0x824C,
+ PtakLata = 0x824E,
+ Podej = 0x8250,
+ GotHint = 0x8252,
+ LawaLeci = 0x8254,
+ PowerKlik = 0x8258,
+ LucekBad = 0x825A,
+ LucekBad1st = 0x825C,
+ IntroDial1 = 0x825E,
+ IntroDial2 = 0x8260,
+ ItsOutro = 0x8262,
+ KamienComment = 0x8264,
+ KamienSkip = 0x8266,
+ TesterFlag = 0x8268,
+ RememberLine = 0x826A,
+ OpisLapek = 0x826C,
+ //OpisKamienia = 0x826E, // Redefinition
+ TalWait = 0x8270,
+ OpisKamienia = 0x8272,
+ JumpBox = 0x8274,
+ JumpBox1 = 0x8276,
+ JumpBox2 = 0x8278,
+ JumpBox3 = 0x827A,
+ SpecPiesek = 0x827C,
+ SpecPiesekCount = 0x827E,
+ SpecPiesekGadanie = 0x8282,
+ ZnikaFlag = 0x8284,
+ ZnikaTimer = 0x8286,
+ SowaTimer = 0x8288,
+ MamrotanieOff = 0x828A,
+ // System flags controlled by script
+ CURRMOB = 0x8400,
+ KOLOR = 0x8402,
+ MBFLAG = 0x8404,
+ MXFLAG = 0x8406,
+ MYFLAG = 0x8408,
+ SCROLLTYPE = 0x840A,
+ SCROLLVALUE = 0x840C,
+ SCROLLVALUE2 = 0x840E,
+ TALKEXITCODE = 0x8410,
+ SPECROUTFLAG1 = 0x8412,
+ SPECROUTFLAG2 = 0x8414,
+ SPECROUTFLAG3 = 0x8416,
+ TALKFLAGCODE = 0x8418,
+ CURRROOM = 0x841A,
+ Talker1Init = 0x841C,
+ Talker2Init = 0x841E,
+ RESTOREROOM = 0x8420,
+ INVALLOWED = 0x8422,
+ BOXSEL = 0x8424,
+ CURSEBLINK = 0x8426,
+ EXACTMOVE = 0x8428,
+ MOVEDESTX = 0x842A,
+ MOVEDESTY = 0x842C,
+ NOANTIALIAS = 0x842E,
+ ESCAPED = 0x8430,
+ ALLOW1OPTION = 0x8432,
+ VOICE_H_LINE = 0x8434,
+ VOICE_A_LINE = 0x8436,
+ VOICE_B_LINE = 0x8438,
+ VOICE_C_LINE = 0x843A,
+ NOHEROATALL = 0x843C,
+ MOUSEENABLED = 0x843E,
+ DIALINES = 0x8440,
+ //SELITEM = 0x8442, // Redefinition
+ SHANWALK = 0x8444,
+ SHANDOG = 0x8446,
+ GETACTIONBACK = 0x8448,
+ GETACTIONDATA = 0x844C,
+ GETACTION = 0x8450,
+ HEROFAST = 0x8452,
+ SELITEM = 0x8454,
+ LMOUSE = 0x8456,
+ MINMX = 0x8458,
+ MAXMX = 0x845A,
+ MINMY = 0x845C,
+ MAXMY = 0x845E,
+ TORX1 = 0x8460,
+ TORY1 = 0x8462,
+ TORX2 = 0x8464,
+ TORY2 = 0x8466,
+ POWER = 0x8468,
+ POWERENABLED = 0x846A,
+ FLCRESTORE = 0x846C,
+ NOCLSTEXT = 0x846E,
+ ESCAPED2 = 0x8470
+ };
+
+ struct FlagDebug {
+ Id id;
+ char flagName[30];
+ };
+
+ static const int kFlagDebugAmount = 368;
+ static const FlagDebug _flagNames[kFlagDebugAmount];
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/font.cpp b/engines/prince/font.cpp
new file mode 100644
index 0000000000..e81a93d1a1
--- /dev/null
+++ b/engines/prince/font.cpp
@@ -0,0 +1,94 @@
+/* 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 "common/archive.h"
+#include "common/debug.h"
+#include "common/stream.h"
+
+#include "prince/font.h"
+#include "prince/prince.h"
+
+namespace Prince {
+
+Font::Font() : _fontData(nullptr) {
+}
+
+Font::~Font() {
+ if (_fontData != nullptr) {
+ free(_fontData);
+ _fontData = nullptr;
+ }
+}
+
+bool Font::loadStream(Common::SeekableReadStream &stream) {
+ stream.seek(0);
+ uint32 dataSize = stream.size();
+ _fontData = (byte *)malloc(dataSize);
+ stream.read(_fontData, stream.size());
+ return true;
+}
+
+int Font::getFontHeight() const {
+ return _fontData[5];
+}
+
+int Font::getMaxCharWidth() const {
+ return 0;
+}
+
+Font::ChrData Font::getChrData(byte chr) const {
+ chr -= 32;
+ uint16 chrOffset = 4 * chr + 6;
+
+ ChrData chrData;
+ chrData._width = _fontData[chrOffset + 2];
+ chrData._height = _fontData[chrOffset + 3];
+ chrData._pixels = _fontData + READ_LE_UINT16(_fontData + chrOffset);
+
+ return chrData;
+}
+
+int Font::getCharWidth(uint32 chr) const {
+ return getChrData(chr)._width;
+}
+
+void Font::drawChar(Graphics::Surface *dst, uint32 chr, int posX, int posY, uint32 color) const {
+ const ChrData chrData = getChrData(chr);
+ Common::Rect screenRect(0, 0, PrinceEngine::kNormalWidth, PrinceEngine::kNormalHeight);
+
+ for (int y = 0; y < chrData._height; y++) {
+ for (int x = 0; x < chrData._width; x++) {
+ byte d = chrData._pixels[x + (chrData._width * y)];
+ if (d == 0) d = 255;
+ else if (d == 1) d = 0;
+ else if (d == 2) d = color;
+ else if (d == 3) d = 0;
+ if (d != 255) {
+ if (screenRect.contains(posX + x, posY + y)) {
+ *(byte *)dst->getBasePtr(posX + x, posY + y) = d;
+ }
+ }
+ }
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/font.h b/engines/prince/font.h
new file mode 100644
index 0000000000..b03849a4aa
--- /dev/null
+++ b/engines/prince/font.h
@@ -0,0 +1,64 @@
+/* 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.
+ */
+
+#ifndef PRINCE_FONT_H
+#define PRINCE_FONT_H
+
+#include "graphics/font.h"
+#include "graphics/surface.h"
+
+#include "common/str.h"
+#include "common/rect.h"
+
+namespace Prince {
+
+class Font : public Graphics::Font {
+public:
+ Font();
+ virtual ~Font();
+
+ bool loadStream(Common::SeekableReadStream &stream);
+
+ virtual int getFontHeight() const override;
+
+ virtual int getMaxCharWidth() const override;
+
+ virtual int getCharWidth(uint32 chr) const override;
+
+ virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+
+ virtual int getKerningOffset(uint32 left, uint32 right) const override { return -2; }
+
+private:
+ struct ChrData {
+ byte *_pixels;
+ byte _width;
+ byte _height;
+ };
+
+ ChrData getChrData(byte chr) const;
+
+ byte *_fontData;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/graphics.cpp b/engines/prince/graphics.cpp
new file mode 100644
index 0000000000..ad6a2ff85c
--- /dev/null
+++ b/engines/prince/graphics.cpp
@@ -0,0 +1,474 @@
+/* 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 "prince/graphics.h"
+#include "prince/prince.h"
+#include "prince/mhwanh.h"
+
+#include "graphics/palette.h"
+
+#include "common/memstream.h"
+
+namespace Prince {
+
+GraphicsMan::GraphicsMan(PrinceEngine *vm) : _vm(vm), _changed(false) {
+ initGraphics(640, 480, true);
+
+ _frontScreen = new Graphics::Surface();
+ _frontScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
+
+ _screenForInventory = new Graphics::Surface();
+ _screenForInventory->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
+
+ _mapScreen = new Graphics::Surface();
+ _mapScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
+
+ _shadowTable70 = (byte *)malloc(256);
+ _shadowTable50 = (byte *)malloc(256);
+}
+
+GraphicsMan::~GraphicsMan() {
+ _frontScreen->free();
+ delete _frontScreen;
+
+ _screenForInventory->free();
+ delete _screenForInventory;
+
+ _mapScreen->free();
+ delete _mapScreen;
+
+ free(_shadowTable70);
+ free(_shadowTable50);
+}
+
+void GraphicsMan::update(Graphics::Surface *screen) {
+ if (_changed) {
+ _vm->_system->copyRectToScreen((byte *)screen->getBasePtr(0, 0), 640, 0, 0, 640, 480);
+
+ _vm->_system->updateScreen();
+ _changed = false;
+ }
+}
+
+void GraphicsMan::setPalette(const byte *palette) {
+ _vm->_system->getPaletteManager()->setPalette(palette, 0, 256);
+}
+
+void GraphicsMan::change() {
+ _changed = true;
+}
+
+void GraphicsMan::draw(Graphics::Surface *screen, const Graphics::Surface *s) {
+ uint16 w = MIN(screen->w, s->w);
+ const byte *src = (const byte *)s->getBasePtr(0, 0);
+ byte *dst = (byte *)screen->getBasePtr(0, 0);
+ for (uint y = 0; y < s->h; y++) {
+ if (y < screen->h) {
+ memcpy(dst, src, w);
+ }
+ src += s->pitch;
+ dst += screen->pitch;
+ }
+ change();
+}
+
+// Black (value = 0) as a primary transparent color, fix for FLC animations
+void GraphicsMan::drawTransparentSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, int secondTransColor) {
+ const byte *src1 = (const byte *)s->getBasePtr(0, 0);
+ byte *dst1 = (byte *)screen->getBasePtr(posX, posY);
+ for (int y = 0; y < s->h; y++) {
+ if (y + posY < screen->h && y + posY >= 0) {
+ const byte *src2 = src1;
+ byte *dst2 = dst1;
+ for (int x = 0; x < s->w; x++, src2++, dst2++) {
+ if (*src2 && *src2 != secondTransColor) {
+ if (x + posX < screen->w && x + posX >= 0) {
+ *dst2 = *src2;
+ }
+ }
+ }
+ }
+ src1 += s->pitch;
+ dst1 += screen->pitch;
+ }
+ change();
+}
+
+/**
+ * Similar to drawTransparentSurface but with use of shadowTable for color recalculation
+ * and kShadowColor (191) as a transparent color.
+ */
+void GraphicsMan::drawAsShadowSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, byte *shadowTable) {
+ const byte *src1 = (const byte *)s->getBasePtr(0, 0);
+ byte *dst1 = (byte *)screen->getBasePtr(posX, posY);
+ for (int y = 0; y < s->h; y++) {
+ if (y + posY < screen->h && y + posY >= 0) {
+ const byte *src2 = src1;
+ byte *dst2 = dst1;
+ for (int x = 0; x < s->w; x++, src2++, dst2++) {
+ if (*src2 == kShadowColor) {
+ if (x + posX < screen->w && x + posX >= 0) {
+ *dst2 = *(shadowTable + *dst2);
+ }
+ }
+ }
+ }
+ src1 += s->pitch;
+ dst1 += screen->pitch;
+ }
+}
+
+/**
+ * Used in glowing animation for inventory items. Creates special blendTable array of colors,
+ * use black (0) as a transparent color.
+ */
+void GraphicsMan::drawTransparentWithBlendSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s) {
+ const byte *src1 = (const byte *)s->getBasePtr(0, 0);
+ byte *dst1 = (byte *)screen->getBasePtr(posX, posY);
+ byte *blendTable = (byte *)malloc(256);
+ for (int i = 0; i < 256; i++) {
+ blendTable[i] = 255;
+ }
+ for (int y = 0; y < s->h; y++) {
+ if (y + posY < screen->h && y + posY >= 0) {
+ const byte *src2 = src1;
+ byte *dst2 = dst1;
+ for (int x = 0; x < s->w; x++, src2++, dst2++) {
+ if (*src2) {
+ if (x + posX < screen->w && x + posX >= 0) {
+ *dst2 = getBlendTableColor(*src2, *dst2, blendTable);
+ }
+ }
+ }
+ }
+ src1 += s->pitch;
+ dst1 += screen->pitch;
+ }
+ free(blendTable);
+ change();
+}
+
+/**
+ * Similar to drawTransparentSurface but with with use of DrawNode as argument for Z axis sorting
+ * and white (255) as transparent color.
+ */
+void GraphicsMan::drawTransparentDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
+ byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
+ byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
+ for (int y = 0; y < drawNode->s->h; y++) {
+ if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
+ byte *src2 = src1;
+ byte *dst2 = dst1;
+ for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
+ if (*src2 != 255) {
+ if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
+ *dst2 = *src2;
+ }
+ }
+ }
+ }
+ src1 += drawNode->s->pitch;
+ dst1 += screen->pitch;
+ }
+}
+
+/**
+ * Similar to drawTransparentDrawNode but with additional anti-aliasing code for sprite drawing.
+ * Edge smoothing is based on 256 x 256 table of colors transition.
+ * Algorithm is checking if currently drawing pixel is located next to the edge of sprite and if it makes jagged line.
+ * If it does then this pixel is set with color from transition table calculated of original background pixel color
+ * and sprite's edge pixel color.
+ */
+void GraphicsMan::drawTransparentWithTransDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
+ // pos of first pixel for each row of source sprite
+ byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
+ // pos of drawing first pixel for each row on screen surface
+ byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
+ // trasition table for calculating new color value
+ byte *transTableData = (byte *)drawNode->data;
+ for (int y = 0; y < drawNode->s->h; y++) {
+ if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
+ // current pixel in row of source sprite
+ byte *src2 = src1;
+ // current pixel in row of screen surface
+ byte *dst2 = dst1;
+ for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
+ if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
+ if (*src2 != 255) {
+ // if source sprite pixel is not mask color than draw it normally
+ *dst2 = *src2;
+ } else {
+ // check for making jagged line
+ if (x) {
+ // not first pixel in row
+ if (*(src2 - 1) == 255) {
+ // if it has mask color to the left - check right
+ if (x != drawNode->s->w - 1) {
+ // not last pixel in row
+ if (*(src2 + 1) == 255) {
+ // pixel to the right with mask color - no anti-alias
+ continue;
+ }
+ // it's not mask color to the right - we continue checking
+ } else {
+ // last pixel in row, no right check - no anti-alias
+ continue;
+ }
+ }
+ // it's not mask color to the left - we continue checking
+ } else if (x != drawNode->s->w - 1) {
+ // first pixel in row but not last - just right pixel checking
+ if (*(src2 + 1) == 255) {
+ // pixel to the right with mask color - no anti-alias
+ continue;
+ }
+ // it's not mask color to the right - we continue checking
+ } else {
+ // it's first and last pixel in row at the same time (width = 1) - no anti-alias
+ continue;
+ }
+ byte value = 0;
+ if (y != drawNode->s->h - 1) {
+ // not last row
+ // check pixel below of current src2 pixel
+ value = *(src2 + drawNode->s->pitch);
+ if (value == 255) {
+ // pixel below with mask color - check above
+ if (y) {
+ // not first row
+ value = *(src2 - drawNode->s->pitch);
+ if (value == 255) {
+ // pixel above with mask color - no anti-alias
+ continue;
+ }
+ // it's not mask color above - we draw as transition color
+ } else {
+ // first row - no anti-alias
+ continue;
+ }
+ }
+ // it's not mask color below - we draw as transition color
+ } else if (y) {
+ // last row - just check above
+ value = *(src2 - drawNode->s->pitch);
+ if (value == 255) {
+ // pixel above with mask color - no anti-alias
+ continue;
+ }
+ // it's not mask color above - we draw as transition color
+ } else {
+ // first and last row at the same time (height = 1) - no anti-alias
+ continue;
+ }
+ // new color value based on orginal screen surface color and sprite's edge pixel color
+ *dst2 = transTableData[*dst2 * 256 + value];
+ }
+ }
+ }
+ }
+ // adding pitch to jump to next row of pixels
+ src1 += drawNode->s->pitch;
+ dst1 += screen->pitch;
+ }
+}
+
+void GraphicsMan::drawMaskDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
+ byte *maskData = (byte *)drawNode->data;
+ byte *src1 = (byte *)drawNode->originalRoomSurface->getBasePtr(drawNode->posX, drawNode->posY);
+ byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
+ int maskWidth = drawNode->width >> 3;
+ int maskPostion = 0;
+ int maskCounter = 128;
+ for (int y = 0; y < drawNode->height; y++) {
+ if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
+ byte *src2 = src1;
+ byte *dst2 = dst1;
+ int tempMaskPostion = maskPostion;
+ for (int x = 0; x < drawNode->width; x++, src2++, dst2++) {
+ if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
+ if ((maskData[tempMaskPostion] & maskCounter) != 0) {
+ *dst2 = *src2;
+ }
+ }
+ maskCounter >>= 1;
+ if (maskCounter == 0) {
+ maskCounter = 128;
+ tempMaskPostion++;
+ }
+ }
+ }
+ src1 += drawNode->originalRoomSurface->pitch;
+ dst1 += screen->pitch;
+ maskPostion += maskWidth;
+ maskCounter = 128;
+ }
+}
+
+void GraphicsMan::drawAsShadowDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
+ byte *shadowData = (byte *)drawNode->data;
+ byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
+ byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
+ for (int y = 0; y < drawNode->s->h; y++) {
+ if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
+ byte *src2 = src1;
+ byte *dst2 = dst1;
+ for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
+ if (*src2 == kShadowColor) {
+ if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
+ *dst2 = *(shadowData + *dst2);
+ }
+ }
+ }
+ }
+ src1 += drawNode->s->pitch;
+ dst1 += screen->pitch;
+ }
+}
+
+void GraphicsMan::drawBackSpriteDrawNode(Graphics::Surface *screen, DrawNode *drawNode) {
+ byte *src1 = (byte *)drawNode->s->getBasePtr(0, 0);
+ byte *dst1 = (byte *)screen->getBasePtr(drawNode->posX, drawNode->posY);
+ for (int y = 0; y < drawNode->s->h; y++) {
+ if (y + drawNode->posY < screen->h && y + drawNode->posY >= 0) {
+ byte *src2 = src1;
+ byte *dst2 = dst1;
+ for (int x = 0; x < drawNode->s->w; x++, src2++, dst2++) {
+ if (*src2 != 255) {
+ if (x + drawNode->posX < screen->w && x + drawNode->posX >= 0) {
+ if (*dst2 == 255) {
+ *dst2 = *src2;
+ }
+ }
+ }
+ }
+ }
+ src1 += drawNode->s->pitch;
+ dst1 += screen->pitch;
+ }
+}
+
+byte GraphicsMan::getBlendTableColor(byte pixelColor, byte backgroundPixelColor, byte *blendTable) {
+ int currColor = 0;
+
+ if (blendTable[pixelColor] != 255) {
+ currColor = blendTable[pixelColor];
+ } else {
+ const byte *originalPalette = _vm->_roomBmp->getPalette();
+
+ int redFirstOrg = originalPalette[pixelColor * 3] * _vm->_mst_shadow / 256;
+ CLIP(redFirstOrg, 0, 255);
+ if (_vm->_mst_shadow <= 256) {
+ int redFirstBack = originalPalette[backgroundPixelColor * 3] * (256 - _vm->_mst_shadow) / 256;
+ CLIP(redFirstBack, 0, 255);
+ redFirstOrg += redFirstBack;
+ CLIP(redFirstOrg, 0, 255);
+ }
+
+ int greenFirstOrg = originalPalette[pixelColor * 3 + 1] * _vm->_mst_shadow / 256;
+ CLIP(greenFirstOrg, 0, 255);
+ if (_vm->_mst_shadow <= 256) {
+ int greenFirstBack = originalPalette[backgroundPixelColor * 3 + 1] * (256 - _vm->_mst_shadow) / 256;
+ CLIP(greenFirstBack, 0, 255);
+ greenFirstOrg += greenFirstBack;
+ CLIP(greenFirstOrg, 0, 255);
+ }
+
+ int blueFirstOrg = originalPalette[pixelColor * 3 + 2] * _vm->_mst_shadow / 256;
+ CLIP(blueFirstOrg, 0, 255);
+ if (_vm->_mst_shadow <= 256) {
+ int blueFirstBack = originalPalette[backgroundPixelColor * 3 + 2] * (256 - _vm->_mst_shadow) / 256;
+ CLIP(blueFirstBack, 0, 255);
+ blueFirstOrg += blueFirstBack;
+ CLIP(blueFirstOrg, 0, 255);
+ }
+
+ int bigValue = PrinceEngine::kIntMax; // infinity
+ for (int j = 0; j < 256; j++) {
+ int redSecondOrg = originalPalette[3 * j];
+ int redNew = redFirstOrg - redSecondOrg;
+ redNew = redNew * redNew;
+
+ int greenSecondOrg = originalPalette[3 * j + 1];
+ int greenNew = greenFirstOrg - greenSecondOrg;
+ greenNew = greenNew * greenNew;
+
+ int blueSecondOrg = originalPalette[3 * j + 2];
+ int blueNew = blueFirstOrg - blueSecondOrg;
+ blueNew = blueNew * blueNew;
+
+ int sumOfColorValues = redNew + greenNew + blueNew;
+
+ if (sumOfColorValues < bigValue) {
+ bigValue = sumOfColorValues;
+ currColor = j;
+ }
+
+ if (sumOfColorValues == 0) {
+ break;
+ }
+ }
+ blendTable[pixelColor] = currColor;
+ }
+ return currColor;
+}
+
+void GraphicsMan::makeShadowTable(int brightness, byte *shadowPalette) {
+ int shadow = brightness * 256 / 100;
+ const byte *originalPalette = _vm->_roomBmp->getPalette();
+
+ for (int i = 0; i < 256; i++) {
+ int redFirstOrg = originalPalette[3 * i] * shadow / 256;
+ int greenFirstOrg = originalPalette[3 * i + 1] * shadow / 256;
+ int blueFirstOrg = originalPalette[3 * i + 2] * shadow / 256;
+
+ int currColor = 0;
+ int bigValue = 999999999; // infinity
+
+ for (int j = 0; j < 256; j++) {
+ int redSecondOrg = originalPalette[3 * j];
+ int redNew = redFirstOrg - redSecondOrg;
+ redNew = redNew * redNew;
+
+ int greenSecondOrg = originalPalette[3 * j + 1];
+ int greenNew = greenFirstOrg - greenSecondOrg;
+ greenNew = greenNew * greenNew;
+
+ int blueSecondOrg = originalPalette[3 * j + 2];
+ int blueNew = blueFirstOrg - blueSecondOrg;
+ blueNew = blueNew * blueNew;
+
+ int sumOfColorValues = redNew + greenNew + blueNew;
+
+ if (sumOfColorValues < bigValue) {
+ bigValue = sumOfColorValues;
+ currColor = j;
+ }
+
+ if (sumOfColorValues == 0) {
+ break;
+ }
+ }
+ shadowPalette[i] = currColor;
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/graphics.h b/engines/prince/graphics.h
new file mode 100644
index 0000000000..b6f002b7da
--- /dev/null
+++ b/engines/prince/graphics.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.
+ *
+ */
+
+#ifndef PRINCE_GRAPHICS_H
+#define PRINCE_GRAPHICS_H
+
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class PrinceEngine;
+class MhwanhDecoder;
+struct DrawNode;
+
+class GraphicsMan {
+public:
+ GraphicsMan(PrinceEngine *vm);
+ ~GraphicsMan();
+
+ void update(Graphics::Surface *screen);
+
+ void change();
+
+ void setPalette(const byte *palette);
+ void makeShadowTable(int brightness, byte *shadowTable);
+
+ void draw(Graphics::Surface *screen, const Graphics::Surface *s);
+ void drawTransparentSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, int secondTransColor = 0);
+ void drawAsShadowSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s, byte *shadowTable);
+ void drawTransparentWithBlendSurface(Graphics::Surface *screen, int32 posX, int32 posY, const Graphics::Surface *s);
+
+ static void drawTransparentDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
+ static void drawTransparentWithTransDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
+ static void drawAsShadowDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
+ static void drawMaskDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
+ static void drawBackSpriteDrawNode(Graphics::Surface *screen, DrawNode *drawNode);
+
+ byte getBlendTableColor(byte pixelColor, byte backgroundPixelColor, byte *blendTable);
+
+ Graphics::Surface *_frontScreen;
+ Graphics::Surface *_screenForInventory;
+ Graphics::Surface *_mapScreen;
+ const Graphics::Surface *_roomBackground;
+
+ byte *_shadowTable70;
+ byte *_shadowTable50;
+
+ static const byte kShadowColor = 191;
+
+private:
+ PrinceEngine *_vm;
+ bool _changed;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp
new file mode 100644
index 0000000000..146470f6b7
--- /dev/null
+++ b/engines/prince/hero.cpp
@@ -0,0 +1,1002 @@
+/* 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 "common/debug.h"
+#include "common/random.h"
+
+#include "prince/hero.h"
+#include "prince/hero_set.h"
+#include "prince/animation.h"
+#include "prince/resource.h"
+#include "prince/prince.h"
+#include "prince/graphics.h"
+#include "prince/flags.h"
+#include "prince/script.h"
+
+namespace Prince {
+
+Hero::Hero(PrinceEngine *vm, GraphicsMan *graph) : _vm(vm), _graph(graph),
+ _number(0), _visible(false), _state(kHeroStateStay), _middleX(0), _middleY(0),
+ _boreNum(1), _currHeight(0), _moveDelay(0), _shadMinus(0), _moveSetType(0), _zoomedHeroSurface(nullptr),
+ _lastDirection(kHeroDirDown), _destDirection(kHeroDirDown), _talkTime(0), _boredomTime(0), _phase(0),
+ _specAnim(nullptr), _drawX(0), _drawY(0), _drawZ(0),
+ _frameXSize(0), _frameYSize(0), _scaledFrameXSize(0), _scaledFrameYSize(0), _color(0),
+ _coords(nullptr), _dirTab(nullptr), _currCoords(nullptr), _currDirTab(nullptr), _step(0),
+ _maxBoredom(200), _leftRightMainDir(0), _upDownMainDir(0), _animSetNr(0)
+{
+}
+
+Hero::~Hero() {
+ freeHeroAnim();
+ freeOldMove();
+ freeZoomedSurface();
+}
+
+bool Hero::loadAnimSet(uint32 animSetNr) {
+ _animSetNr = animSetNr;
+
+ if (animSetNr >= ARRAYSIZE(heroSetTable)) {
+ return false;
+ }
+
+ _shadMinus = heroSetBack[animSetNr];
+
+ for (uint32 i = 0; i < _moveSet.size(); i++) {
+ delete _moveSet[i];
+ }
+
+ const HeroSetAnimNames &animSet = *heroSetTable[animSetNr];
+
+ _moveSet.resize(kMoveSetSize);
+ for (uint32 i = 0; i < kMoveSetSize; i++) {
+ debug("Anim set item %d %s", i, animSet[i]);
+ Animation *anim = nullptr;
+ if (animSet[i] != nullptr) {
+ anim = new Animation();
+ Resource::loadResource(anim, animSet[i], false);
+ }
+ _moveSet[i] = anim;
+ }
+
+ return true;
+}
+
+Graphics::Surface *Hero::getSurface() {
+ Animation *heroAnim = nullptr;
+ if (_specAnim != nullptr) {
+ heroAnim = _specAnim;
+ } else {
+ heroAnim = _moveSet[_moveSetType];
+ }
+
+ if (heroAnim != nullptr) {
+ int16 phaseFrameIndex = heroAnim->getPhaseFrameIndex(_phase);
+ Graphics::Surface *heroFrame = heroAnim->getFrame(phaseFrameIndex);
+ return heroFrame;
+ }
+ return nullptr;
+}
+
+uint16 Hero::getData(AttrId dataId) {
+ switch (dataId) {
+ case kHeroLastDir:
+ return _lastDirection;
+ case kHeroAnimSet:
+ return _animSetNr;
+ default:
+ assert(false);
+ return 0;
+ }
+}
+
+int Hero::getScaledValue(int size) {
+ int16 initScaleValue = _vm->_scaleValue;
+ if (_vm->_scaleValue != 10000) {
+ int newSize = 0;
+ for (int i = 0; i < size; i++) {
+ initScaleValue -= 100;
+ if (initScaleValue >= 0) {
+ newSize++;
+ } else {
+ initScaleValue += _vm->_scaleValue;
+ }
+ }
+ return newSize;
+ } else {
+ return size;
+ }
+}
+
+Graphics::Surface *Hero::zoomSprite(Graphics::Surface *heroFrame) {
+ Graphics::Surface *zoomedFrame = new Graphics::Surface();
+ zoomedFrame->create(_scaledFrameXSize, _scaledFrameYSize, Graphics::PixelFormat::createFormatCLUT8());
+
+ int sprZoomX;
+ int sprZoomY = _vm->_scaleValue;
+ uint xSource = 0;
+ uint ySource = 0;
+ uint xDest = 0;
+ uint yDest = 0;
+
+ for (int i = 0; i < _scaledFrameYSize; i++) {
+ // linear_loop:
+ while (1) {
+ sprZoomY -= 100;
+ if (sprZoomY >= 0 || _vm->_scaleValue == 10000) {
+ // all_r_y
+ sprZoomX = _vm->_scaleValue;
+ break; // to loop_lin
+ } else {
+ sprZoomY += _vm->_scaleValue;
+ xSource = 0;
+ ySource++;
+ }
+ }
+ // loop_lin:
+ for (int j = 0; j < _scaledFrameXSize; j++) {
+ sprZoomX -= 100;
+ if (sprZoomX >= 0) {
+ // its_all_r
+ memcpy(zoomedFrame->getBasePtr(xDest, yDest), heroFrame->getBasePtr(xSource, ySource), 1);
+ xDest++;
+ } else {
+ sprZoomX += _vm->_scaleValue;
+ j--;
+ }
+ xSource++;
+ }
+ xDest = 0;
+ yDest++;
+ xSource = 0;
+ ySource++;
+ }
+ return zoomedFrame;
+}
+
+void Hero::countDrawPosition() {
+ Animation *heroAnim = nullptr;
+ if (_specAnim != nullptr) {
+ heroAnim = _specAnim;
+ } else {
+ heroAnim = _moveSet[_moveSetType];
+ }
+ if (heroAnim != nullptr) {
+ int phaseFrameIndex = heroAnim->getPhaseFrameIndex(_phase);
+ Graphics::Surface *heroSurface = heroAnim->getFrame(phaseFrameIndex);
+
+ _frameXSize = heroSurface->w;
+ _frameYSize = heroSurface->h;
+ _scaledFrameXSize = getScaledValue(_frameXSize);
+ _scaledFrameYSize = getScaledValue(_frameYSize);
+
+ if (_vm->_scaleValue != 10000) {
+ //notfullSize
+ _drawX = _middleX - _scaledFrameXSize / 2;
+ _drawY = _middleY + 1 - _scaledFrameYSize;
+ _vm->checkMasks(_drawX, _drawY - 1, _scaledFrameXSize, _scaledFrameYSize, _middleY);
+ } else {
+ //fullSize
+ _drawX = _middleX - _frameXSize / 2;
+ _drawY = _middleY + 1 - _frameYSize;
+ _vm->checkMasks(_drawX, _drawY - 1, _frameXSize, _frameYSize, _middleY);
+ }
+ _drawZ = _middleY;
+ }
+}
+
+void Hero::showHeroShadow(Graphics::Surface *screen, DrawNode *drawNode) {
+ PrinceEngine *vm = (PrinceEngine *)drawNode->data;
+ int16 heroSurfaceWidth = drawNode->s->w;
+ int16 heroSurfaceHeight = drawNode->s->h;
+
+ Graphics::Surface *makeShadow = new Graphics::Surface();
+ makeShadow->create(heroSurfaceWidth, heroSurfaceHeight, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int y = 0; y < heroSurfaceHeight; y++) {
+ byte *src = (byte *)drawNode->s->getBasePtr(0, y);
+ byte *dst = (byte *)makeShadow->getBasePtr(0, y);
+ for (int x = 0; x < heroSurfaceWidth; x++, dst++, src++) {
+ if (*src != 0xFF) {
+ *dst = GraphicsMan::kShadowColor;
+ } else {
+ *dst = *src;
+ }
+ }
+ }
+
+ if (drawNode->posY > 1 && drawNode->posY < PrinceEngine::kMaxPicHeight) {
+ int shadDirection;
+ if (vm->_lightY > drawNode->posY) {
+ shadDirection = 1;
+ } else {
+ shadDirection = 0;
+ }
+
+ vm->_shadLineLen = 0;
+ Graphics::drawLine(vm->_lightX, vm->_lightY, drawNode->posX, drawNode->posY, 0, &vm->plotShadowLinePoint, vm);
+
+ byte *sprShadow = vm->_graph->_shadowTable70;
+
+ int shadDrawX = drawNode->posX - vm->_picWindowX;
+ int shadDrawY = drawNode->posY - vm->_picWindowY;
+
+ int shadPosX = shadDrawX;
+ int shadPosY = shadDrawY;
+ int shadBitAddr = drawNode->posY * PrinceEngine::kMaxPicWidth / 8 + drawNode->posX / 8;
+ int shadBitMask = 128 >> (drawNode->posX % 8);
+
+ int shadZoomY2 = vm->_shadScaleValue;
+ int shadZoomY = drawNode->scaleValue;
+
+ int diffX = 0;
+ int diffY = 0;
+
+ int shadowHeroX = 0;
+ int shadowHeroY = heroSurfaceHeight - 1;
+
+ int shadLastY = 0;
+
+ byte *shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY); // first pixel from last row of shadow hero
+ byte *background = (byte *)screen->getBasePtr(shadDrawX, shadDrawY); // pixel of background where shadow sprite starts
+
+ // banked2
+ byte *shadowLineStart = vm->_shadowLine + 8;
+
+ int shadWallDown = 0;
+ int shadWallBitAddr = 0;
+ int shadWallBitMask = 0;
+ byte *shadWallDestAddr = 0;
+ int shadWallPosY = 0;
+ int shadWallSkipX = 0;
+ int shadWallModulo = 0;
+
+ // linear_loop
+ for (int i = 0; i < heroSurfaceHeight; i++) {
+ int j;
+ //retry_line:
+ for (j = heroSurfaceHeight - i; j > 0; j--) {
+ shadZoomY -= 100;
+ if (shadZoomY < 0 && drawNode->scaleValue != 10000) {
+ shadZoomY += drawNode->scaleValue;
+ shadowHeroY--;
+ if (shadowHeroY < 0) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (!j) {
+ break;
+ }
+ if (shadowHeroY < 0) {
+ break;
+ }
+
+ //line_y_ok
+ if (shadLastY != shadPosY && shadPosY >= 0 && shadPosY < 480 && shadPosX < 640) {
+ shadLastY = shadPosY;
+ bool skipLineFlag = false;
+ int shadSkipX = 0;
+ int ctLoop = 0;
+ int sprModulo = 0;
+
+ if (shadPosX < 0) {
+ shadSkipX = -1 * shadPosX;
+ if (heroSurfaceWidth > shadSkipX) {
+ ctLoop = heroSurfaceWidth - shadSkipX;
+ shadowHeroX = shadSkipX;
+ } else {
+ //skip_line
+ skipLineFlag = true;
+ }
+ } else {
+ //x1_ok
+ if (shadPosX + heroSurfaceWidth > 640) {
+ ctLoop = 640 - shadPosX;
+ sprModulo = shadPosX + heroSurfaceWidth - 640;
+ } else {
+ //draw_line
+ ctLoop = heroSurfaceWidth;
+ }
+ }
+
+ if (!skipLineFlag) {
+ //draw_line1
+ //retry_line2
+ int k;
+ for (k = j; k > 0; k--) {
+ shadZoomY2 -= 100;
+ if (shadZoomY2 < 0 && vm->_shadScaleValue != 10000) {
+ shadZoomY2 += vm->_shadScaleValue;
+ shadowHeroY--;
+ if (shadowHeroY < 0) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (shadowHeroY < 0) {
+ break;
+ }
+ if (!k) {
+ break;
+ }
+ //line_y_ok_2:
+ //copy_trans
+ bool shadWDFlag = false;
+ int shadZoomX = drawNode->scaleValue;
+ int backgroundDiff = shadSkipX;
+ int shadBitMaskCopyTrans = shadBitMask;
+ int shadBitAddrCopyTrans = shadBitAddr;
+ shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
+ background = (byte *)screen->getBasePtr(shadDrawX + diffX + backgroundDiff, shadDrawY + diffY);
+
+ if (shadPosX < 0) {
+ if (heroSurfaceWidth > shadSkipX) {
+ shadBitAddrCopyTrans += shadSkipX / 8;
+ if ((shadSkipX % 8)) {
+ //loop_rotate:
+ for (int a = 0; a < (shadSkipX % 8); a++) {
+ if (shadBitMaskCopyTrans == 1) {
+ shadBitMaskCopyTrans = 128;
+ shadBitAddrCopyTrans++;
+ } else {
+ shadBitMaskCopyTrans >>= 1;
+ }
+ }
+ }
+ }
+ }
+
+ //ct_loop:
+ for (int l = 0; l < ctLoop; l++) {
+ shadZoomX -= 100;
+ if (shadZoomX < 0 && drawNode->scaleValue != 10000) {
+ shadZoomX += drawNode->scaleValue;
+ } else {
+ if (*shadowHero == GraphicsMan::kShadowColor) {
+ if ((shadBitMaskCopyTrans & vm->_shadowBitmap[shadBitAddrCopyTrans])) {
+ if (shadWallDown == 0) {
+ if ((shadBitMaskCopyTrans & vm->_shadowBitmap[shadBitAddrCopyTrans + PrinceEngine::kShadowBitmapSize])) {
+ shadWDFlag = true;
+ //shadow
+ *background = *(sprShadow + *background);
+ }
+ }
+ } else {
+ //shadow
+ *background = *(sprShadow + *background);
+ }
+ }
+ //ct_next
+ if (shadBitMaskCopyTrans == 1) {
+ shadBitMaskCopyTrans = 128;
+ shadBitAddrCopyTrans++;
+ } else {
+ shadBitMaskCopyTrans >>= 1;
+ }
+ //okok
+ backgroundDiff++;
+ background = (byte *)screen->getBasePtr(shadDrawX + diffX + backgroundDiff, shadDrawY + diffY);
+ }
+ shadowHeroX++;
+ shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
+ }
+ //byebyebye
+ if (!shadWallDown && shadWDFlag) {
+ shadWallDown = shadPosX;
+ shadWallBitAddr = shadBitAddr;
+ shadWallDestAddr = (byte *)screen->getBasePtr(shadDrawX + diffX, shadDrawY + diffY);
+ shadWallBitMask = shadBitMask;
+ shadWallPosY = shadPosY;
+ shadWallSkipX = shadSkipX;
+ shadWallModulo = sprModulo;
+ }
+ //byebye
+ if (shadDirection && shadWallDown) {
+ int shadBitMaskWallCopyTrans = shadWallBitMask;
+ int shadBitAddrWallCopyTrans = shadWallBitAddr;
+ background = shadWallDestAddr;
+ shadowHero = (byte *)makeShadow->getBasePtr(shadWallSkipX, shadowHeroY);
+
+ if (ctLoop > shadWallSkipX && ctLoop - shadWallSkipX > shadWallModulo) {
+ //WALL_copy_trans
+ shadWDFlag = false;
+ int shadZoomXWall = drawNode->scaleValue;
+ int backgroundDiffWall = 0;
+ int shadowHeroXWall = 0;
+ //ct_loop:
+ for (int m = 0; m < ctLoop; m++) {
+ shadZoomXWall -= 100;
+ if (shadZoomXWall < 0 && drawNode->scaleValue != 10000) {
+ shadZoomXWall += drawNode->scaleValue;
+ } else {
+ //point_ok:
+ if (*shadowHero == GraphicsMan::kShadowColor) {
+ if ((shadBitMaskWallCopyTrans & vm->_shadowBitmap[shadBitAddrWallCopyTrans + PrinceEngine::kShadowBitmapSize])) {
+ *background = *(sprShadow + *background);
+ }
+ }
+ //ct_next
+ if (shadBitMaskWallCopyTrans == 1) {
+ shadBitMaskWallCopyTrans = 128;
+ shadBitAddrWallCopyTrans++;
+ } else {
+ shadBitMaskWallCopyTrans >>= 1;
+ }
+ //okok
+ backgroundDiffWall++;
+ background = shadWallDestAddr + backgroundDiffWall;
+ }
+ shadowHeroXWall++;
+ shadowHero = (byte *)makeShadow->getBasePtr(shadWallSkipX + shadowHeroXWall, shadowHeroY);
+ }
+ }
+ //krap2
+ shadWallDestAddr -= PrinceEngine::kNormalWidth;
+ shadWallBitAddr -= PrinceEngine::kMaxPicWidth / 8;
+ shadWallPosY--;
+ }
+ }
+ }
+ //skip_line
+ //next_line
+ if (READ_LE_UINT16(shadowLineStart + 2) < READ_LE_UINT16(shadowLineStart - 2)) {
+ //minus_y
+ shadBitAddr -= PrinceEngine::kMaxPicWidth / 8;
+ shadPosY--;
+ diffY--;
+ } else if (READ_LE_UINT16(shadowLineStart + 2) > READ_LE_UINT16(shadowLineStart - 2)) {
+ shadBitAddr += PrinceEngine::kMaxPicWidth / 8;
+ shadPosY++;
+ diffY++;
+ }
+ //no_change_y
+ if (READ_LE_UINT16(shadowLineStart) < READ_LE_UINT16(shadowLineStart - 4)) {
+ //minus_x
+ shadPosX--;
+ //rol
+ if (shadBitMask == 128) {
+ shadBitMask = 1;
+ shadBitAddr--;
+ } else {
+ shadBitMask <<= 1;
+ }
+ diffX--;
+ } else if (READ_LE_UINT16(shadowLineStart) > READ_LE_UINT16(shadowLineStart - 4)) {
+ shadPosX++;
+ //ror
+ if (shadBitMask == 1) {
+ shadBitMask = 128;
+ shadBitAddr++;
+ } else {
+ shadBitMask >>= 1;
+ }
+ diffX++;
+ }
+ //no_change_x
+ shadowLineStart += 4;
+ shadowHeroY--;
+ if (shadowHeroY < 0) {
+ break;
+ }
+ shadowHeroX = 0;
+ background = (byte *)screen->getBasePtr(shadDrawX + diffX, shadDrawY + diffY);
+ shadowHero = (byte *)makeShadow->getBasePtr(shadowHeroX, shadowHeroY);
+ }
+ //koniec_bajki - end_of_a_story
+ }
+ makeShadow->free();
+ delete makeShadow;
+}
+
+void Hero::setScale(int8 zoomBitmapValue) {
+ if (!zoomBitmapValue) {
+ _vm->_scaleValue = 10000;
+ } else {
+ _vm->_scaleValue = 10000 / zoomBitmapValue;
+ }
+}
+
+void Hero::selectZoom() {
+ int8 zoomBitmapValue = *(_vm->_zoomBitmap + _middleY / 4 * _vm->kZoomBitmapWidth + _middleX / 4);
+ setScale(zoomBitmapValue);
+}
+
+int Hero::rotateHero(int oldDirection, int newDirection) {
+ switch (oldDirection) {
+ case kHeroDirLeft:
+ switch (newDirection) {
+ case kHeroDirRight:
+ return kMove_MLR;
+ case kHeroDirUp:
+ return kMove_MLU;
+ case kHeroDirDown:
+ return kMove_MLD;
+ }
+ break;
+ case kHeroDirRight:
+ switch (newDirection) {
+ case kHeroDirLeft:
+ return kMove_MRL;
+ case kHeroDirUp:
+ return kMove_MRU;
+ case kHeroDirDown:
+ return kMove_MRD;
+ }
+ break;
+ case kHeroDirUp:
+ switch (newDirection) {
+ case kHeroDirLeft:
+ return kMove_MUL;
+ case kHeroDirRight:
+ return kMove_MUR;
+ case kHeroDirDown:
+ return kMove_MUD;
+ }
+ break;
+ case kHeroDirDown:
+ switch (newDirection) {
+ case kHeroDirLeft:
+ return kMove_MDL;
+ case kHeroDirRight:
+ return kMove_MDR;
+ case kHeroDirUp:
+ return kMove_MDU;
+ }
+ break;
+ }
+ error("rotateHero - wrong directions - old %d, new %d", oldDirection, newDirection);
+}
+
+void Hero::heroStanding() {
+ _phase = 0;
+ switch (_lastDirection) {
+ case kHeroDirLeft:
+ _moveSetType = kMove_SL;
+ break;
+ case kHeroDirRight:
+ _moveSetType = kMove_SR;
+ break;
+ case kHeroDirUp:
+ _moveSetType = kMove_SU;
+ break;
+ case kHeroDirDown:
+ _moveSetType = kMove_SD;
+ break;
+ }
+}
+
+void Hero::showHero() {
+ if (_visible && !_vm->_flags->getFlagValue(Flags::NOHEROATALL)) {
+
+ if (_talkTime != 0) {
+ _talkTime--;
+ }
+
+ // Scale of hero
+ selectZoom();
+
+ if (_state != kHeroStateStay) {
+ _boredomTime = 0;
+ }
+
+ if (_state == kHeroStateSpec) {
+ if (_specAnim != nullptr) {
+ if (_phase < _specAnim->getPhaseCount() - 1) {
+ _phase++;
+ } else {
+ if (!_talkTime) {
+ _state = kHeroStateStay;
+ } else {
+ _state = kHeroStateTalk;
+ }
+ countDrawPosition();
+ return;
+ }
+ } else {
+ _state = kHeroStateStay;
+ }
+ } else {
+ freeHeroAnim();
+ }
+
+ if (_state == kHeroStateTalk) {
+ if (_talkTime) {
+ switch (_lastDirection) {
+ case kHeroDirLeft:
+ _moveSetType = kMove_TL;
+ break;
+ case kHeroDirRight:
+ _moveSetType = kMove_TR;
+ break;
+ case kHeroDirUp:
+ _moveSetType = kMove_TU;
+ break;
+ case kHeroDirDown:
+ _moveSetType = kMove_TD;
+ break;
+ }
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) {
+ _phase++;
+ } else {
+ _phase = _moveSet[_moveSetType]->getLoopCount();
+ }
+ } else {
+ _state = kHeroStateStay;
+ }
+ }
+
+ if (_state == kHeroStateBore) {
+ switch (_boreNum) {
+ case 0:
+ _moveSetType = kMove_BORED1;
+ break;
+ case 1:
+ _moveSetType = kMove_BORED2;
+ break;
+ }
+ if (_moveSet[_moveSetType] != nullptr) {
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) {
+ _phase++;
+ } else {
+ _phase = 0;
+ _lastDirection = kHeroDirDown;
+ _state = kHeroStateStay;
+ }
+ } else {
+ _state = kHeroStateStay;
+ }
+ }
+
+ if (_state == kHeroStateStay) {
+ if (!_vm->_optionsFlag) {
+ if (!_vm->_interpreter->getLastOPCode() || !_vm->_interpreter->getFgOpcodePC()) {
+ _boredomTime++;
+ if (_boredomTime == _maxBoredom) {
+ _boreNum =_vm->_randomSource.getRandomNumber(1); // rand one of two 'bored' animation
+ _phase = 0;
+ _state = kHeroStateBore;
+ if (_lastDirection == kHeroDirUp) {
+ _lastDirection = kHeroDirLeft;
+ } else {
+ _lastDirection = kHeroDirDown;
+ }
+ }
+ } else {
+ _boredomTime = 0;
+ }
+ } else {
+ _boredomTime = 0;
+ }
+ heroStanding();
+ }
+
+ if (_state == kHeroStateTurn) {
+ if (_destDirection && (_lastDirection != _destDirection)) {
+ _phase = 0;
+ int rotateDir = rotateHero(_lastDirection, _destDirection);
+ _lastDirection = _destDirection;
+ if (rotateDir) {
+ _moveSetType = rotateDir;
+ _state = kHeroStateTran;
+ } else {
+ _state = kHeroStateStay;
+ heroStanding();
+ }
+ } else {
+ _state = kHeroStateStay;
+ heroStanding();
+ }
+ }
+
+ if (_state == kHeroStateTran) {
+ if (_moveSet[_moveSetType] != nullptr) {
+ // only in bear form
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) {
+ _phase += 2;
+ } else {
+ _state = kHeroStateStay;
+ heroStanding();
+ }
+ } else {
+ _state = kHeroStateStay;
+ heroStanding();
+ }
+ }
+
+ if (_state == kHeroStateMvan) {
+ if (_moveSet[_moveSetType] != nullptr) {
+ // only in bear form
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) {
+ _phase += 2;
+ } else {
+ _state = kHeroStateMove;
+ }
+ } else {
+ _state = kHeroStateMove;
+ }
+ }
+
+ if (_state == kHeroStateDelayMove) {
+ _moveDelay--;
+ if (!_moveDelay) {
+ _state = kHeroStateMove;
+ }
+ }
+
+ if (_state == kHeroStateMove || _state == kHeroStateRun) {
+ //go_for_it:
+ while (1) {
+ if (_currCoords != nullptr) {
+ if (READ_LE_UINT32(_currCoords) != 0xFFFFFFFF) {
+ int x = READ_LE_UINT16(_currCoords);
+ int y = READ_LE_UINT16(_currCoords + 2);
+ _currCoords += 4;
+ int dir = *_currDirTab;
+ _currDirTab++;
+ if (_lastDirection != dir) {
+ _phase = 0;
+ int rotateDir = rotateHero(_lastDirection, dir);
+ _lastDirection = dir;
+ if (_moveSet[rotateDir] != nullptr) {
+ // only in bear form
+ _state = kHeroStateMvan;
+ _moveSetType = rotateDir;
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) {
+ _phase += 2;
+ break;
+ } else {
+ _state = kHeroStateMove;
+ continue;
+ }
+ } else {
+ continue;
+ }
+ }
+ //no_need_direction_change
+ if (dir == kHeroDirLeft) {
+ if (_middleX - x >= _step) {
+ heroMoveGotIt(x, y, dir);
+ break;
+ }
+ } else if (dir == kHeroDirRight) {
+ if (x - _middleX >= _step) {
+ heroMoveGotIt(x, y, dir);
+ break;
+ }
+ } else if (dir == kHeroDirUp) {
+ if (_middleY - y >= _step) {
+ heroMoveGotIt(x, y, dir);
+ break;
+ }
+ } else if (dir == kHeroDirDown) {
+ if (y - _middleY >= _step) {
+ heroMoveGotIt(x, y, dir);
+ break;
+ }
+ }
+ } else {
+ //finito
+ _middleX = READ_LE_UINT16(_currCoords - 4);
+ _middleY = READ_LE_UINT16(_currCoords - 2);
+ selectZoom();
+
+ if (_coords != nullptr) {
+ free(_coords);
+ _coords = nullptr;
+ _currCoords = nullptr;
+ }
+
+ if (_dirTab != nullptr) {
+ free(_dirTab);
+ _dirTab = nullptr;
+ _currDirTab = nullptr;
+ }
+
+ _boredomTime = 0;
+ _phase = 0;
+ _state = kHeroStateTurn;
+
+ if (!_destDirection) {
+ _destDirection = _lastDirection;
+ }
+
+ heroStanding();
+
+ break;
+ }
+ } else {
+ heroStanding();
+ break;
+ }
+ }
+ }
+ countDrawPosition();
+ }
+}
+
+void Hero::drawHero() {
+ if (_visible && !_vm->_flags->getFlagValue(Flags::NOHEROATALL)) {
+ freeZoomedSurface();
+ Graphics::Surface *mainHeroSurface = getSurface();
+ if (mainHeroSurface) {
+ DrawNode newDrawNode;
+ newDrawNode.posX = _drawX;
+ newDrawNode.posY = _drawY;
+ newDrawNode.posZ = _drawZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = _vm->_transTable;
+ newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
+
+ if (_vm->_scaleValue != 10000) {
+ _zoomedHeroSurface = zoomSprite(mainHeroSurface);
+ newDrawNode.s = _zoomedHeroSurface;
+ } else {
+ newDrawNode.s = mainHeroSurface;
+ }
+ _vm->_drawNodeList.push_back(newDrawNode);
+
+ drawHeroShadow(mainHeroSurface);
+
+ }
+ }
+}
+
+void Hero::drawHeroShadow(Graphics::Surface *heroFrame) {
+ DrawNode newDrawNode;
+ newDrawNode.posX = _middleX - _scaledFrameXSize / 2;
+ newDrawNode.posY = _middleY - _shadMinus - 1;
+ newDrawNode.posZ = kHeroShadowZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.scaleValue = _vm->_scaleValue;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = _vm;
+ newDrawNode.drawFunction = &showHeroShadow;
+ newDrawNode.s = heroFrame;
+ _vm->_drawNodeList.push_back(newDrawNode);
+}
+
+void Hero::heroMoveGotIt(int x, int y, int dir) {
+ _middleX = x;
+ _middleY = y;
+ selectZoom();
+
+ switch (dir) {
+ case kHeroDirLeft:
+ _moveSetType = kMove_ML;
+ break;
+ case kHeroDirRight:
+ _moveSetType = kMove_MR;
+ break;
+ case kHeroDirUp:
+ _moveSetType = kMove_MU;
+ break;
+ case kHeroDirDown:
+ _moveSetType = kMove_MD;
+ break;
+ }
+
+ if (_vm->_flags->getFlagValue(Flags::HEROFAST) || _state == kHeroStateRun) {
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 2) {
+ _phase += 2;
+ } else {
+ _phase = 0;
+ }
+ } else {
+ if (_phase < _moveSet[_moveSetType]->getPhaseCount() - 1) {
+ _phase++;
+ } else {
+ _phase = 0;
+ }
+ }
+
+ _step = kStepLeftRight;
+ if (_moveSetType == kMove_MU || _moveSetType == kMove_MD) {
+ _step = kStepUpDown;
+ }
+ if (_vm->_flags->getFlagValue(Flags::HEROFAST)) {
+ _step *= 2.5;
+ } else if (_state == kHeroStateRun) {
+ _step *= 2;
+ }
+}
+
+void Hero::scrollHero() {
+ int scrollType = _vm->_flags->getFlagValue(Flags::SCROLLTYPE);
+ int position = _middleX;
+ int scrollValue, scrollValue2;
+
+ switch (scrollType) {
+ case 0:
+ position = _middleX;
+ break;
+ case 1:
+ scrollValue = _vm->_flags->getFlagValue(Flags::SCROLLVALUE);
+ position = _vm->_normAnimList[scrollValue]._currX + _vm->_normAnimList[scrollValue]._currW / 2;
+ break;
+ case 2:
+ scrollValue = _vm->_flags->getFlagValue(Flags::SCROLLVALUE);
+ scrollValue2 = _vm->_flags->getFlagValue(Flags::SCROLLVALUE2);
+ position = scrollValue;
+ if (scrollValue < scrollValue2) {
+ _vm->_flags->setFlagValue(Flags::SCROLLVALUE, 0);
+ } else {
+ _vm->_flags->setFlagValue(Flags::SCROLLVALUE, scrollValue - scrollValue2);
+ }
+ break;
+ }
+
+ int locationWidth = _vm->_sceneWidth;
+ int difference = locationWidth - _vm->kNormalWidth / 2;
+
+ int destValue = 0;
+ if (position > _vm->kNormalWidth / 2) {
+ destValue = difference - _vm->kNormalWidth / 2;
+ }
+ if (position < difference) {
+ destValue = position - _vm->kNormalWidth / 2;
+ }
+
+ if(destValue < 0) {
+ destValue = 0;
+ }
+ _vm->_picWindowX = destValue;
+ _drawX -= destValue;
+}
+
+void Hero::freeOldMove() {
+ if (_coords != nullptr) {
+ free(_coords);
+ _coords = nullptr;
+ }
+ if (_dirTab != nullptr) {
+ free(_dirTab);
+ _dirTab = nullptr;
+ }
+ _step = 0;
+ _phase = 0;
+ _moveDelay = 0;
+ _state = Hero::kHeroStateStay;
+}
+
+void Hero::freeHeroAnim() {
+ if (_specAnim != nullptr) {
+ delete _specAnim;
+ _specAnim = nullptr;
+ }
+}
+
+void Hero::freeZoomedSurface() {
+ if (_zoomedHeroSurface != nullptr) {
+ _zoomedHeroSurface->free();
+ delete _zoomedHeroSurface;
+ _zoomedHeroSurface = nullptr;
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/hero.h b/engines/prince/hero.h
new file mode 100644
index 0000000000..d5f7d8cc7a
--- /dev/null
+++ b/engines/prince/hero.h
@@ -0,0 +1,184 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_HERO_H
+#define PRINCE_HERO_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/memstream.h"
+
+#include "graphics/surface.h"
+#include "graphics/primitives.h"
+
+namespace Prince {
+
+class Animation;
+class PrinceEngine;
+class GraphicsMan;
+struct InventoryItem;
+struct DrawNode;
+
+class Hero {
+public:
+ static const uint32 kMoveSetSize = 26;
+ static const int16 kStepLeftRight = 8;
+ static const int16 kStepUpDown = 4;
+ static const int16 kHeroShadowZ = 2;
+
+ enum State {
+ kHeroStateStay,
+ kHeroStateTurn,
+ kHeroStateMove,
+ kHeroStateBore,
+ kHeroStateSpec,
+ kHeroStateTalk,
+ kHeroStateMvan,
+ kHeroStateTran,
+ kHeroStateRun,
+ kHeroStateDelayMove
+ };
+
+ enum Direction {
+ kHeroDirLeft = 1,
+ kHeroDirRight = 2,
+ kHeroDirUp = 3,
+ kHeroDirDown = 4
+ };
+
+ enum MoveSet {
+ kMove_SL,
+ kMove_SR,
+ kMove_SU,
+ kMove_SD,
+ kMove_ML,
+ kMove_MR,
+ kMove_MU,
+ kMove_MD,
+ kMove_TL,
+ kMove_TR,
+ kMove_TU,
+ kMove_TD,
+ kMove_MLU,
+ kMove_MLD,
+ kMove_MLR,
+ kMove_MRU,
+ kMove_MRD,
+ kMove_MRL,
+ kMove_MUL,
+ kMove_MUR,
+ kMove_MUD,
+ kMove_MDL,
+ kMove_MDR,
+ kMove_MDU,
+ kMove_BORED1,
+ kMove_BORED2
+ };
+
+ // Used instead of offset in getData
+ enum AttrId {
+ kHeroLastDir = 26,
+ kHeroAnimSet = 120
+ };
+
+ uint16 getData(AttrId dataId);
+
+ Hero(PrinceEngine *vm, GraphicsMan *graph);
+ ~Hero();
+ bool loadAnimSet(uint32 heroAnimNumber);
+
+ Graphics::Surface *getSurface();
+
+ void setPos(int16 x, int16 y) { _middleX = x; _middleY = y; }
+ void setVisible(bool flag) { _visible = flag; }
+
+ void showHero();
+ void drawHero();
+ void freeZoomedSurface();
+ void heroStanding();
+ void heroMoveGotIt(int x, int y, int dir);
+ int rotateHero(int oldDirection, int newDirection);
+ void scrollHero();
+ void setScale(int8 zoomBitmapValue);
+ int getScaledValue(int size);
+ void selectZoom();
+ void countDrawPosition();
+ Graphics::Surface *zoomSprite(Graphics::Surface *heroFrame);
+ void line(int x1, int y1, int x2, int y2);
+ void plotPoint(int x, int y);
+ static void showHeroShadow(Graphics::Surface *screen, DrawNode *drawNode);
+ void drawHeroShadow(Graphics::Surface *heroFrame);
+ void freeOldMove();
+ void freeHeroAnim();
+
+ uint16 _number;
+ uint16 _visible;
+ int16 _state;
+ int16 _middleX; // middle of X
+ int16 _middleY; // lower part of hero
+ int16 _moveSetType;
+
+ int16 _frameXSize;
+ int16 _frameYSize;
+ int16 _scaledFrameXSize;
+ int16 _scaledFrameYSize;
+ int16 _drawX;
+ int16 _drawY;
+ int16 _drawZ;
+
+ byte *_coords; // array of coordinates
+ byte *_dirTab; // array of directions
+ byte *_currCoords; // current coordinations
+ byte *_currDirTab; // current direction
+ int16 _lastDirection; // previous move direction
+ int16 _destDirection;
+ int16 _leftRightMainDir; // left or right - dominant direction
+ int16 _upDownMainDir; // up or down - dominant direction
+ int32 _phase; // Phase animation phase
+ int16 _step; // Step x/y step size depends on direction
+ int16 _maxBoredom; // stand still timeout
+ int16 _boredomTime; // Boredom current boredom time in frames
+ uint16 _boreNum; // Bore anim frame
+ int16 _talkTime; // TalkTime time of talk anim
+ Animation *_specAnim; // additional anim
+ Graphics::Surface *_zoomedHeroSurface;
+
+ uint16 _currHeight; // height of current anim phase
+
+ Common::Array<byte> _inventory; // Inventory array of items
+ Common::Array<byte> _inventory2; // Inventory2 array of items
+ // Font subtitiles font
+ int _color; // subtitles color
+ uint32 _animSetNr; // number of animation set
+ Common::Array<Animation *> _moveSet; // MoveAnims MoveSet
+
+ uint32 _moveDelay;
+ uint32 _shadMinus;
+
+private:
+ PrinceEngine *_vm;
+ GraphicsMan *_graph;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/hero_set.h b/engines/prince/hero_set.h
new file mode 100644
index 0000000000..dfe7e50268
--- /dev/null
+++ b/engines/prince/hero_set.h
@@ -0,0 +1,244 @@
+/* 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 "common/scummsys.h"
+
+namespace Prince {
+
+const int heroSetBack[7] = { 0, 0, 10, 0, 6, 0, 0 };
+
+typedef const char *HeroSetAnimNames[26];
+
+static HeroSetAnimNames heroSet5 = {
+ "SL_DIAB.ANI",
+ "SR_DIAB.ANI",
+ "SU_DIAB.ANI",
+ "SD_DIAB.ANI",
+ nullptr,
+ nullptr,
+ "MU_DIAB.ANI",
+ "MD_DIAB.ANI",
+ "TL_DIAB.ANI",
+ "TR_DIAB.ANI",
+ "TU_DIAB.ANI",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr
+};
+
+static HeroSetAnimNames heroSet1 = {
+ "SL_HERO1.ANI",
+ "SR_HERO1.ANI",
+ "SU_HERO1.ANI",
+ "SD_HERO1.ANI",
+ "ML_HERO1.ANI",
+ "MR_HERO1.ANI",
+ "MU_HERO1.ANI",
+ "MD_HERO1.ANI",
+ "TL_HERO1.ANI",
+ "TR_HERO1.ANI",
+ "TU_HERO1.ANI",
+ "TD_HERO1.ANI",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ "KSI_KURZ.ANI",
+ "KS_WLOSY.ANI"
+};
+
+static HeroSetAnimNames heroSet2 = {
+ "SL_HERO2.ANI",
+ "SR_HERO2.ANI",
+ "SU_HERO2.ANI",
+ "SD_HERO2.ANI",
+ "ML_HERO2.ANI",
+ "MR_HERO2.ANI",
+ "MU_HERO2.ANI",
+ "MD_HERO2.ANI",
+ "TL_HERO2.ANI",
+ "TR_HERO2.ANI",
+ "TU_HERO2.ANI",
+ "TD_HERO2.ANI",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ "KSI_KU_S.ANI",
+ "KS_WLO_S.ANI"
+};
+
+static HeroSetAnimNames heroSet3 = {
+ "SL_BEAR.ANI",
+ "SR_BEAR.ANI",
+ "SU_BEAR.ANI",
+ "SD_BEAR.ANI",
+ "NIED-LEW.ANI",
+ "NIED-PRW.ANI",
+ "NIED-TYL.ANI",
+ "NIED-PRZ.ANI",
+ "SL_BEAR.ANI",
+ "SR_BEAR.ANI",
+ "SU_BEAR.ANI",
+ "SD_BEAR.ANI",
+ "N_LW-TYL.ANI",
+ "N_LW-PRZ.ANI",
+ "N_LW-PR.ANI",
+ "N_PR-TYL.ANI",
+ "N_PR-PRZ.ANI",
+ "N_PR-LW.ANI",
+ "N_TYL-LW.ANI",
+ "N_TYL-PR.ANI",
+ "N_TL-PRZ.ANI",
+ "N_PRZ-LW.ANI",
+ "N_PRZ-PR.ANI",
+ "N_PRZ-TL.ANI",
+ nullptr,
+ nullptr,
+};
+
+static HeroSetAnimNames shanSet1 = {
+ "SL_SHAN.ANI",
+ "SR_SHAN.ANI",
+ "SU_SHAN.ANI",
+ "SD_SHAN.ANI",
+ "ML_SHAN.ANI",
+ "MR_SHAN.ANI",
+ "MU_SHAN.ANI",
+ "MD_SHAN.ANI",
+ "TL_SHAN.ANI",
+ "TR_SHAN.ANI",
+ "TU_SHAN.ANI",
+ "TD_SHAN.ANI",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ "B1_SHAN.ANI",
+ "B2_SHAN.ANI",
+};
+
+static HeroSetAnimNames shanSet2 = {
+ "SL_SHAN2.ANI",
+ "SR_SHAN2.ANI",
+ "SU_SHAN.ANI",
+ "SD_SHAN2.ANI",
+ "ML_SHAN2.ANI",
+ "MR_SHAN2.ANI",
+ "MU_SHAN.ANI",
+ "MD_SHAN2.ANI",
+ "TL_SHAN2.ANI",
+ "TR_SHAN2.ANI",
+ "TU_SHAN.ANI",
+ "TD_SHAN2.ANI",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ "B1_SHAN2.ANI",
+ "B2_SHAN2.ANI"
+};
+
+static HeroSetAnimNames arivSet1 = {
+ "SL_ARIV.ANI",
+ "SR_ARIV.ANI",
+ "SU_ARIV.ANI",
+ "SD_ARIV.ANI",
+ "ML_ARIV.ANI",
+ "MR_ARIV.ANI",
+ "MU_ARIV.ANI",
+ "MD_ARIV.ANI",
+ "TL_ARIV.ANI",
+ "TR_ARIV.ANI",
+ "TU_ARIV.ANI",
+ "TD_ARIV.ANI",
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr
+};
+
+const HeroSetAnimNames *heroSetTable[7] = {
+ &heroSet1,
+ &heroSet2,
+ &heroSet3,
+ &shanSet1,
+ &arivSet1,
+ &heroSet5,
+ &shanSet2,
+};
+
+} // End of namespace Prince
diff --git a/engines/prince/mhwanh.cpp b/engines/prince/mhwanh.cpp
new file mode 100644
index 0000000000..ef94ef71f9
--- /dev/null
+++ b/engines/prince/mhwanh.cpp
@@ -0,0 +1,71 @@
+/* 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 "common/stream.h"
+
+#include "graphics/surface.h"
+
+#include "prince/mhwanh.h"
+
+namespace Prince {
+
+MhwanhDecoder::MhwanhDecoder() : _surface(nullptr), _palette(nullptr) {
+}
+
+MhwanhDecoder::~MhwanhDecoder() {
+ destroy();
+}
+
+void MhwanhDecoder::destroy() {
+ if (_surface != nullptr) {
+ _surface->free();
+ delete _surface;
+ _surface = nullptr;
+ }
+ if (_palette != nullptr) {
+ free(_palette);
+ _palette = nullptr;
+ }
+}
+
+bool MhwanhDecoder::loadStream(Common::SeekableReadStream &stream) {
+ destroy();
+ stream.seek(0);
+ stream.skip(0x20);
+ // Read the palette
+ _palette = (byte *)malloc(kPaletteColorCount * 3);
+ for (uint16 i = 0; i < kPaletteColorCount; i++) {
+ _palette[i * 3] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 + 2] = stream.readByte();
+ }
+
+ _surface = new Graphics::Surface();
+ _surface->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
+ for (int h = 0; h < 480; h++) {
+ stream.read(_surface->getBasePtr(0, h), 640);
+ }
+
+ return true;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/mhwanh.h b/engines/prince/mhwanh.h
new file mode 100644
index 0000000000..f8165a7666
--- /dev/null
+++ b/engines/prince/mhwanh.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_MHWANH_H
+#define PRINCE_MHWANH_H
+
+#include "image/image_decoder.h"
+#include "image/bmp.h"
+
+#include "graphics/surface.h"
+
+#include "resource.h"
+
+namespace Prince {
+
+class MhwanhDecoder : public Image::ImageDecoder {
+public:
+ MhwanhDecoder();
+ virtual ~MhwanhDecoder();
+
+ // ImageDecoder API
+ void destroy();
+ virtual bool loadStream(Common::SeekableReadStream &stream);
+ virtual Graphics::Surface *getSurface() const { return _surface; }
+ virtual const byte *getPalette() const { return _palette; }
+ uint16 getPaletteCount() const { return kPaletteColorCount; }
+ static const uint16 kPaletteColorCount = 256;
+
+private:
+ Graphics::Surface *_surface;
+ byte *_palette;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/mob.cpp b/engines/prince/mob.cpp
new file mode 100644
index 0000000000..de825ef8b2
--- /dev/null
+++ b/engines/prince/mob.cpp
@@ -0,0 +1,108 @@
+/* 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 "prince/mob.h"
+
+namespace Prince {
+
+bool Mob::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+
+ uint16 visible = stream.readUint16LE();
+
+ if (visible == 0xFFFF)
+ return false;
+
+ _visible = visible;
+ _type = stream.readUint16LE();
+ _rect.left = stream.readUint16LE();
+ _rect.top = stream.readUint16LE();
+ _rect.right = stream.readUint16LE();
+ _rect.bottom = stream.readUint16LE();
+
+ _mask = stream.readUint16LE();
+
+ _examPosition.x = stream.readUint16LE();
+ _examPosition.y = stream.readUint16LE();
+ _examDirection = (Direction)stream.readUint16LE();
+
+ _usePosition.x = stream.readByte();
+ _usePosition.y = stream.readByte();
+ _useDirection = (Direction)stream.readUint16LE();
+
+ uint32 nameOffset = stream.readUint32LE();
+ uint32 examTextOffset = stream.readUint32LE();
+
+ byte c;
+ stream.seek(nameOffset);
+ _name.clear();
+ while ((c = stream.readByte()))
+ _name += c;
+
+ stream.seek(examTextOffset);
+ _examText.clear();
+ c = stream.readByte();
+ if (c) {
+ _examText += c;
+ do {
+ c = stream.readByte();
+ _examText += c;
+ } while (c != 255);
+ }
+ stream.seek(pos + 32);
+
+ return true;
+}
+
+void Mob::setData(AttrId dataId, uint16 value) {
+ switch (dataId) {
+ case kMobExamDir:
+ _examDirection = (Direction)value;
+ break;
+ case kMobExamX:
+ _examPosition.x = value;
+ break;
+ case kMobExamY:
+ _examPosition.y = value;
+ break;
+ default:
+ assert(false);
+ }
+}
+
+uint16 Mob::getData(AttrId dataId) {
+ switch (dataId) {
+ case kMobVisible:
+ return _visible;
+ case kMobExamDir:
+ return _examDirection;
+ case kMobExamX:
+ return _examPosition.x;
+ case kMobExamY:
+ return _examPosition.y;
+ default:
+ assert(false);
+ return 0;
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/mob.h b/engines/prince/mob.h
new file mode 100644
index 0000000000..cc60e36f9b
--- /dev/null
+++ b/engines/prince/mob.h
@@ -0,0 +1,70 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_MOB_H
+#define PRINCE_MOB_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+#include "prince/common.h"
+
+namespace Prince {
+
+class Mob {
+public:
+
+ Mob() : _name(""), _examText("") {}
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+
+ // Used instead of offset in setData and getData
+ enum AttrId {
+ kMobVisible = 0,
+ kMobExamX = 14,
+ kMobExamY = 16,
+ kMobExamDir = 18
+ };
+
+ void setData(AttrId dataId, uint16 value);
+ uint16 getData(AttrId dataId);
+
+ bool _visible;
+ uint16 _type;
+ uint16 _mask;
+ Common::Rect _rect;
+
+ Common::Point _examPosition;
+ Direction _examDirection;
+
+ Common::Point _usePosition;
+ Direction _useDirection;
+
+ Common::String _name;
+ Common::String _examText;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/module.mk b/engines/prince/module.mk
new file mode 100644
index 0000000000..b1be123d4b
--- /dev/null
+++ b/engines/prince/module.mk
@@ -0,0 +1,30 @@
+MODULE := engines/prince
+
+MODULE_OBJS = \
+ animation.o \
+ archive.o \
+ cursor.o \
+ debugger.o \
+ decompress.o \
+ detection.o \
+ flags.o \
+ font.o \
+ graphics.o \
+ hero.o \
+ mhwanh.o \
+ mob.o \
+ object.o \
+ prince.o \
+ pscr.o \
+ saveload.o \
+ script.o \
+ sound.o \
+ variatxt.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_PRINCE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/prince/musNum.h b/engines/prince/musNum.h
new file mode 100644
index 0000000000..c24cba6ad7
--- /dev/null
+++ b/engines/prince/musNum.h
@@ -0,0 +1,87 @@
+/* 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.
+ *
+ */
+
+namespace Prince {
+
+enum RoomMus {
+ ROOM01MUS = 3,
+ ROOM02MUS = 9,
+ ROOM03MUS = 9,
+ ROOM04MUS = 9,
+ ROOM05MUS = 13,
+ ROOM06MUS = 9,
+ ROOM07MUS = 9,
+ ROOM08MUS = 9,
+ ROOM09MUS = 14,
+ ROOM10MUS = 9,
+ ROOM11MUS = 9,
+ ROOM12MUS = 9,
+ ROOM13MUS = 9,
+ ROOM14MUS = 9,
+ ROOM15MUS = 5,
+ ROOM16MUS = 5,
+ ROOM17MUS = 5,
+ ROOM18MUS = 5,
+ ROOM19MUS = 5,
+ ROOM20MUS = 12,
+ ROOM21MUS = 9,
+ ROOM22MUS = 9,
+ ROOM23MUS = 1,
+ ROOM24MUS = 1,
+ ROOM25MUS = 2,
+ ROOM26MUS = 10,
+ ROOM27MUS = 7,
+ ROOM28MUS = 10,
+ ROOM29MUS = 10,
+ ROOM30MUS = 11,
+ ROOM31MUS = 14,
+ ROOM32MUS = 11,
+ ROOM33MUS = 7,
+ ROOM34MUS = 7,
+ ROOM35MUS = 7,
+ ROOM36MUS = 7,
+ ROOM37MUS = 7,
+ ROOM38MUS = 7,
+ ROOM39MUS = 7,
+ ROOM40MUS = 7,
+ ROOM41MUS = 7,
+ ROOM42MUS = 7,
+ ROOM43MUS = 15,
+ ROOM46MUS = 100,
+ ROOM47MUS = 100,
+ ROOM48MUS = 100,
+ ROOM49MUS = 100,
+ ROOM50MUS = 100,
+ ROOM51MUS = 12,
+ ROOM52MUS = 9,
+ ROOM53MUS = 5,
+ ROOM54MUS = 11,
+ ROOM55MUS = 11,
+ ROOM56MUS = 11,
+ ROOM57MUS = 7,
+ ROOM58MUS = 13,
+ ROOM59MUS = 16,
+ ROOM60MUS = 4,
+ ROOM61MUS = 0
+};
+
+} // End of namespace Prince
diff --git a/engines/prince/object.cpp b/engines/prince/object.cpp
new file mode 100644
index 0000000000..a9a96455b1
--- /dev/null
+++ b/engines/prince/object.cpp
@@ -0,0 +1,113 @@
+/* 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 "common/archive.h"
+#include "common/debug-channels.h"
+#include "common/debug.h"
+#include "common/stream.h"
+
+#include "graphics/surface.h"
+
+#include "prince/object.h"
+
+namespace Prince {
+
+Object::Object() : _surface(nullptr), _x(0), _y(0), _z(0), _flags(0), _width(0),
+ _height(0), _zoomTime(0), _zoomSurface(nullptr)
+{
+}
+
+Object::~Object() {
+ if (_surface != nullptr) {
+ _surface->free();
+ delete _surface;
+ _surface = nullptr;
+ }
+ if (_zoomSurface != nullptr) {
+ _zoomSurface->free();
+ delete _zoomSurface;
+ _zoomSurface = nullptr;
+ }
+}
+
+void Object::loadSurface(Common::SeekableReadStream &stream) {
+ stream.skip(4);
+ _width = stream.readUint16LE();
+ _height = stream.readUint16LE();
+ _surface = new Graphics::Surface();
+ _surface->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int h = 0; h < _surface->h; h++) {
+ stream.read(_surface->getBasePtr(0, h), _surface->w);
+ }
+}
+
+bool Object::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+ uint16 x = stream.readUint16LE();
+ if (x == 0xFFFF) {
+ return false;
+ }
+ _x = x;
+ _y = stream.readSint16LE(); // skull mini-game has some signed y coords
+
+ const Common::String obStreamName = Common::String::format("OB%02d", stream.readUint16LE());
+ Common::SeekableReadStream *obStream = SearchMan.createReadStreamForMember(obStreamName);
+ if (obStream) {
+ loadSurface(*obStream);
+ }
+ delete obStream;
+
+ _flags = stream.readUint16LE();
+ _z = stream.readUint16LE();
+
+ stream.seek(pos + 16);
+
+ return true;
+}
+
+void Object::setData(AttrId dataId, int32 value) {
+ switch (dataId) {
+ case kObjectX:
+ _x = value;
+ break;
+ case kObjectY:
+ _y = value;
+ break;
+ default:
+ assert(false);
+ }
+}
+
+int32 Object::getData(AttrId dataId) {
+ switch (dataId) {
+ case kObjectX:
+ return _x;
+ case kObjectY:
+ return _y;
+ default:
+ assert(false);
+ return 0;
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/object.h b/engines/prince/object.h
new file mode 100644
index 0000000000..68edd061a0
--- /dev/null
+++ b/engines/prince/object.h
@@ -0,0 +1,70 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_OBJECT_H
+#define PRINCE_OBJECT_H
+
+#include "image/image_decoder.h"
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class Object {
+public:
+ Object();
+ ~Object();
+
+ int32 _x;
+ int32 _y;
+ int32 _z;
+ uint16 _width;
+ uint16 _height;
+ int32 _flags;
+ int32 _zoomTime;
+ Graphics::Surface *_zoomSurface;
+
+ // Used instead of offset in setData and getData
+ enum AttrId {
+ kObjectAddr = 0,
+ kObjectX = 4,
+ kObjectY = 6,
+ kObjectZ = 8,
+ kObjectFlags = 10,
+ kObjectZoomInSource = 12,
+ kObjectZoomInLen = 16,
+ kObjectZoomInAddr = 20,
+ kObjectZoomInTime = 24
+ };
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+ Graphics::Surface *getSurface() const { return _surface; }
+ int32 getData(AttrId dataId);
+ void setData(AttrId dataId, int32 value);
+
+private:
+ void loadSurface(Common::SeekableReadStream &stream);
+ Graphics::Surface *_surface;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/option_text.h b/engines/prince/option_text.h
new file mode 100644
index 0000000000..d4d214c98c
--- /dev/null
+++ b/engines/prince/option_text.h
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ */
+
+namespace Prince {
+
+// PL - Mazovia coding
+const char invOptionsTextPL[5][18] = {
+ "Obejrzyj",
+ "U\xa7""yj",
+ "Otw\xa2""rz/Pchnij",
+ "Zamknij/Poci\x86""gnij",
+ "Daj"
+};
+
+const char optionsTextPL[7][18] = {
+ "Podejd\xa6",
+ "Obejrzyj",
+ "Zabierz",
+ "U\xa7""yj",
+ "Otw\xa2""rz/Pchnij",
+ "Zamknij/Poci\x86""gnij",
+ "Porozmawiaj"
+};
+
+// DE - Other font then for PL + ISO 8859-2 or Windows-1250
+// + special letter values changing
+// Normal value: 196, 214, 220, 223, 228, 246, 252
+// Prince change: 131, 132, 133, 127, 128, 129, 130
+char invOptionsTextDE[5][17] = {
+ "Anschauen",
+ "Benutzen",
+ "\x84""ffnen/Sto\x7f""en",
+ "Schlie\x7f""en/Ziehen",
+ "Geben"
+};
+
+const char optionsTextDE[7][17] = {
+ "Hingehen",
+ "Anschauen",
+ "Wegnehmen",
+ "Benutzen",
+ "\x84""ffnen/Sto\x7f""en",
+ "Schlie\x7f""en/Ziehen",
+ "Ansprechen"
+};
+
+// EN
+const char *invOptionsTextEN[] = {
+ "Examine",
+ "Use",
+ "Open/Push",
+ "Close/Pull",
+ "Give"
+};
+
+const char *optionsTextEN[] = {
+ "Walk to",
+ "Examine",
+ "Pick up",
+ "Use",
+ "Open/Push",
+ "Close/Pull",
+ "Talk to"
+};
+
+} // End of namespace Prince
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
new file mode 100644
index 0000000000..b0f2cd5056
--- /dev/null
+++ b/engines/prince/prince.cpp
@@ -0,0 +1,4733 @@
+/* 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 "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/random.h"
+#include "common/fs.h"
+#include "common/keyboard.h"
+#include "common/substream.h"
+#include "common/str.h"
+
+#include "graphics/cursorman.h"
+#include "graphics/surface.h"
+#include "graphics/palette.h"
+#include "graphics/pixelformat.h"
+
+#include "engines/util.h"
+#include "engines/advancedDetector.h"
+
+#include "audio/audiostream.h"
+
+#include "prince/prince.h"
+#include "prince/font.h"
+#include "prince/graphics.h"
+#include "prince/script.h"
+#include "prince/debugger.h"
+#include "prince/object.h"
+#include "prince/mob.h"
+#include "prince/sound.h"
+#include "prince/variatxt.h"
+#include "prince/flags.h"
+#include "prince/font.h"
+#include "prince/mhwanh.h"
+#include "prince/cursor.h"
+#include "prince/archive.h"
+#include "prince/hero.h"
+#include "prince/resource.h"
+#include "prince/animation.h"
+#include "prince/option_text.h"
+#include "prince/curve_values.h"
+
+namespace Prince {
+
+void PrinceEngine::debugEngine(const char *s, ...) {
+ char buf[STRINGBUFLEN];
+ va_list va;
+
+ va_start(va, s);
+ vsnprintf(buf, STRINGBUFLEN, s, va);
+ va_end(va);
+
+ debug("Prince::Engine %s", buf);
+}
+
+PrinceEngine::PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc) :
+ Engine(syst), _gameDescription(gameDesc), _graph(nullptr), _script(nullptr), _interpreter(nullptr), _flags(nullptr),
+ _locationNr(0), _debugger(nullptr), _midiPlayer(nullptr), _room(nullptr),
+ _cursor1(nullptr), _cursor2(nullptr), _cursor3(nullptr), _font(nullptr),
+ _suitcaseBmp(nullptr), _roomBmp(nullptr), _cursorNr(0), _picWindowX(0), _picWindowY(0), _randomSource("prince"),
+ _invLineX(134), _invLineY(176), _invLine(5), _invLines(3), _invLineW(70), _invLineH(76), _maxInvW(72), _maxInvH(76),
+ _invLineSkipX(2), _invLineSkipY(3), _showInventoryFlag(false), _inventoryBackgroundRemember(false),
+ _mst_shadow(0), _mst_shadow2(0), _candleCounter(0), _invX1(53), _invY1(18), _invWidth(536), _invHeight(438),
+ _invCurInside(false), _optionsFlag(false), _optionEnabled(0), _invExamY(120), _invMaxCount(2), _invCounter(0),
+ _optionsMob(-1), _currentPointerNumber(1), _selectedMob(-1), _selectedItem(0), _selectedMode(0),
+ _optionsWidth(210), _optionsHeight(170), _invOptionsWidth(210), _invOptionsHeight(130), _optionsStep(20),
+ _invOptionsStep(20), _optionsNumber(7), _invOptionsNumber(5), _optionsColor1(236), _optionsColor2(252),
+ _dialogWidth(600), _dialogHeight(0), _dialogLineSpace(10), _dialogColor1(220), _dialogColor2(223),
+ _dialogFlag(false), _dialogLines(0), _dialogText(nullptr), _mouseFlag(1),
+ _roomPathBitmap(nullptr), _roomPathBitmapTemp(nullptr), _coordsBufEnd(nullptr), _coordsBuf(nullptr), _coords(nullptr),
+ _traceLineLen(0), _rembBitmapTemp(nullptr), _rembBitmap(nullptr), _rembMask(0), _rembX(0), _rembY(0), _fpX(0), _fpY(0),
+ _checkBitmapTemp(nullptr), _checkBitmap(nullptr), _checkMask(0), _checkX(0), _checkY(0), _traceLineFirstPointFlag(false),
+ _tracePointFirstPointFlag(false), _coordsBuf2(nullptr), _coords2(nullptr), _coordsBuf3(nullptr), _coords3(nullptr),
+ _shanLen(0), _directionTable(nullptr), _currentMidi(0), _lightX(0), _lightY(0), _curveData(nullptr), _curvPos(0),
+ _creditsData(nullptr), _creditsDataSize(0), _currentTime(0), _zoomBitmap(nullptr), _shadowBitmap(nullptr), _transTable(nullptr),
+ _flcFrameSurface(nullptr), _shadScaleValue(0), _shadLineLen(0), _scaleValue(0), _dialogImage(nullptr) {
+
+ // Debug/console setup
+ DebugMan.addDebugChannel(DebugChannel::kScript, "script", "Prince Script debug channel");
+ DebugMan.addDebugChannel(DebugChannel::kEngine, "engine", "Prince Engine debug channel");
+
+ DebugMan.enableDebugChannel("script");
+
+ memset(_audioStream, 0, sizeof(_audioStream));
+
+ gDebugLevel = 10;
+}
+
+PrinceEngine::~PrinceEngine() {
+ DebugMan.clearAllDebugChannels();
+
+ delete _rnd;
+ delete _debugger;
+ delete _cursor1;
+ delete _cursor3;
+ delete _midiPlayer;
+ delete _script;
+ delete _flags;
+ delete _interpreter;
+ delete _font;
+ delete _roomBmp;
+ delete _suitcaseBmp;
+ delete _variaTxt;
+ free(_talkTxt);
+ free(_invTxt);
+ free(_dialogDat);
+ delete _graph;
+ delete _room;
+
+ if (_cursor2 != nullptr) {
+ _cursor2->free();
+ delete _cursor2;
+ }
+
+ for (uint i = 0; i < _objList.size(); i++) {
+ delete _objList[i];
+ }
+ _objList.clear();
+
+ free(_objSlot);
+
+ for (uint32 i = 0; i < _pscrList.size(); i++) {
+ delete _pscrList[i];
+ }
+ _pscrList.clear();
+
+ for (uint i = 0; i < _maskList.size(); i++) {
+ free(_maskList[i]._data);
+ }
+ _maskList.clear();
+
+ _drawNodeList.clear();
+
+ clearBackAnimList();
+ _backAnimList.clear();
+
+ freeAllNormAnims();
+ _normAnimList.clear();
+
+ for (uint i = 0; i < _allInvList.size(); i++) {
+ _allInvList[i]._surface->free();
+ delete _allInvList[i]._surface;
+ }
+ _allInvList.clear();
+
+ _optionsPic->free();
+ delete _optionsPic;
+
+ _optionsPicInInventory->free();
+ delete _optionsPicInInventory;
+
+ for (uint i = 0; i < _mainHero->_moveSet.size(); i++) {
+ delete _mainHero->_moveSet[i];
+ }
+
+ for (uint i = 0; i < _secondHero->_moveSet.size(); i++) {
+ delete _secondHero->_moveSet[i];
+ }
+
+ delete _mainHero;
+ delete _secondHero;
+
+ free(_roomPathBitmap);
+ free(_roomPathBitmapTemp);
+ free(_coordsBuf);
+
+ _mobPriorityList.clear();
+
+ freeAllSamples();
+
+ free(_zoomBitmap);
+ free(_shadowBitmap);
+ free(_transTable);
+
+ free(_curveData);
+
+ free(_shadowLine);
+
+ free(_creditsData);
+
+ if (_dialogImage != nullptr) {
+ _dialogImage->free();
+ delete _dialogImage;
+ }
+}
+
+GUI::Debugger *PrinceEngine::getDebugger() {
+ return _debugger;
+}
+
+void PrinceEngine::init() {
+
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+
+ debugEngine("Adding all path: %s", gameDataDir.getPath().c_str());
+
+ PtcArchive *all = new PtcArchive();
+ if (!all->open("all/databank.ptc"))
+ error("Can't open all/databank.ptc");
+
+ PtcArchive *voices = new PtcArchive();
+ if (!voices->open("data/voices/databank.ptc"))
+ error("Can't open data/voices/databank.ptc");
+
+ PtcArchive *sound = new PtcArchive();
+ if (!sound->open("sound/databank.ptc"))
+ error("Can't open sound/databank.ptc");
+
+ SearchMan.addSubDirectoryMatching(gameDataDir, "all");
+
+ SearchMan.add("all", all);
+ SearchMan.add("voices", voices);
+ SearchMan.add("sound", sound);
+
+ _graph = new GraphicsMan(this);
+
+ _rnd = new Common::RandomSource("prince");
+
+ _midiPlayer = new MusicPlayer(this);
+
+ if (getLanguage() == Common::DE_DEU) {
+ _font = new Font();
+ Resource::loadResource(_font, "font3.raw", true);
+ } else {
+ _font = new Font();
+ Resource::loadResource(_font, "font1.raw", true);
+ }
+
+ _suitcaseBmp = new MhwanhDecoder();
+ Resource::loadResource(_suitcaseBmp, "walizka", true);
+
+ _script = new Script(this);
+ Resource::loadResource(_script, "skrypt.dat", true);
+
+ _flags = new InterpreterFlags();
+ _interpreter = new Interpreter(this, _script, _flags);
+
+ _debugger = new Debugger(this, _flags);
+
+ _variaTxt = new VariaTxt();
+ Resource::loadResource(_variaTxt, "variatxt.dat", true);
+
+ _cursor1 = new Cursor();
+ Resource::loadResource(_cursor1, "mouse1.cur", true);
+
+ _cursor3 = new Cursor();
+ Resource::loadResource(_cursor3, "mouse2.cur", true);
+
+ Common::SeekableReadStream *talkTxtStream = SearchMan.createReadStreamForMember("talktxt.dat");
+ if (!talkTxtStream) {
+ error("Can't load talkTxtStream");
+ return;
+ }
+ _talkTxtSize = talkTxtStream->size();
+ _talkTxt = (byte *)malloc(_talkTxtSize);
+ talkTxtStream->read(_talkTxt, _talkTxtSize);
+
+ delete talkTxtStream;
+
+ Common::SeekableReadStream *invTxtStream = SearchMan.createReadStreamForMember("invtxt.dat");
+ if (!invTxtStream) {
+ error("Can't load invTxtStream");
+ return;
+ }
+ _invTxtSize = invTxtStream->size();
+ _invTxt = (byte *)malloc(_invTxtSize);
+ invTxtStream->read(_invTxt, _invTxtSize);
+
+ delete invTxtStream;
+
+ loadAllInv();
+
+ Common::SeekableReadStream *dialogDatStream = SearchMan.createReadStreamForMember("dialog.dat");
+ if (!dialogDatStream) {
+ error("Can't load dialogDatStream");
+ return;
+ }
+ _dialogDatSize = dialogDatStream->size();
+ _dialogDat = (byte *)malloc(_dialogDatSize);
+ dialogDatStream->read(_dialogDat, _dialogDatSize);
+
+ delete dialogDatStream;
+
+ _optionsPic = new Graphics::Surface();
+ _optionsPic->create(_optionsWidth, _optionsHeight, Graphics::PixelFormat::createFormatCLUT8());
+ Common::Rect picRect(0, 0, _optionsWidth, _optionsHeight);
+ _optionsPic->fillRect(picRect, _graph->kShadowColor);
+
+ _optionsPicInInventory = new Graphics::Surface();
+ _optionsPicInInventory->create(_invOptionsWidth, _invOptionsHeight, Graphics::PixelFormat::createFormatCLUT8());
+ Common::Rect invPicRect(0, 0, _invOptionsWidth, _invOptionsHeight);
+ _optionsPicInInventory->fillRect(invPicRect, _graph->kShadowColor);
+
+ _roomBmp = new Image::BitmapDecoder();
+
+ _room = new Room();
+
+ _mainHero = new Hero(this, _graph);
+ _secondHero = new Hero(this, _graph);
+ _secondHero->_maxBoredom = 140;
+ _secondHero->loadAnimSet(3);
+
+ _roomPathBitmap = (byte *)malloc(kPathBitmapLen);
+ _roomPathBitmapTemp = (byte *)malloc(kPathBitmapLen);
+ _coordsBuf = (byte *)malloc(kTracePts * 4);
+ _coords = _coordsBuf;
+ _coordsBufEnd = _coordsBuf + kTracePts * 4 - 4;
+
+ BackgroundAnim tempBackAnim;
+ tempBackAnim._seq._currRelative = 0;
+ for (int i = 0; i < kMaxBackAnims; i++) {
+ _backAnimList.push_back(tempBackAnim);
+ }
+
+ Anim tempAnim;
+ tempAnim._animData = nullptr;
+ tempAnim._shadowData = nullptr;
+ for (int i = 0; i < kMaxNormAnims; i++) {
+ _normAnimList.push_back(tempAnim);
+ }
+
+ _objSlot = (uint16 *)malloc(kMaxObjects * sizeof(uint16));
+ for (int i = 0; i < kMaxObjects; i++) {
+ _objSlot[i] = 0xFF;
+ }
+
+ _zoomBitmap = (byte *)malloc(kZoomBitmapLen);
+ _shadowBitmap = (byte *)malloc(2 * kShadowBitmapSize);
+ _transTable = (byte *)malloc(kTransTableSize);
+
+ _curveData = (int16 *)malloc(2 * kCurveLen * sizeof(int16));
+
+ _shadowLine = (byte *)malloc(kShadowLineArraySize);
+
+ Common::SeekableReadStream *creditsDataStream = SearchMan.createReadStreamForMember("credits.dat");
+ if (!creditsDataStream) {
+ error("Can't load creditsDataStream");
+ return;
+ }
+ _creditsDataSize = creditsDataStream->size();
+ _creditsData = (byte *)malloc(_creditsDataSize);
+ creditsDataStream->read(_creditsData, _creditsDataSize);
+ delete creditsDataStream;
+}
+
+void PrinceEngine::showLogo() {
+ MhwanhDecoder logo;
+ _system->delayMillis(1000 / kFPS * 20);
+ if (Resource::loadResource(&logo, "logo.raw", true)) {
+ loadSample(0, "LOGO.WAV");
+ playSample(0, 0);
+ _graph->draw(_graph->_frontScreen, logo.getSurface());
+ _graph->change();
+ _graph->update(_graph->_frontScreen);
+ setPalette(logo.getPalette());
+ _system->delayMillis(1000 / kFPS * 70);
+ }
+}
+
+Common::Error PrinceEngine::run() {
+
+ init();
+
+ showLogo();
+
+ mainLoop();
+
+ return Common::kNoError;
+}
+
+bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+
+ uint16 type = stream.readUint16LE();
+ if (type == 0xFFFF) {
+ return false;
+ }
+ _type = type;
+ _fileNumber = stream.readUint16LE();
+ _startPhase = stream.readUint16LE();
+ _endPhase = stream.readUint16LE();
+ _loopPhase = stream.readUint16LE();
+ _x = stream.readSint16LE();
+ _y = stream.readSint16LE();
+ _loopType = stream.readUint16LE();
+ _nextAnim = stream.readUint16LE();
+ _flags = stream.readUint16LE();
+
+ //debug("AnimListItem type %d, fileNumber %d, x %d, y %d, flags %d", _type, _fileNumber, _x, _y, _flags);
+ //debug("startPhase %d, endPhase %d, loopPhase %d", _startPhase, _endPhase, _loopPhase);
+
+ // 32 byte aligment
+ stream.seek(pos + 32);
+
+ return true;
+}
+
+bool PrinceEngine::loadLocation(uint16 locationNr) {
+
+ blackPalette();
+
+ _flicPlayer.close();
+
+ memset(_textSlots, 0, sizeof(_textSlots));
+ freeAllSamples();
+
+ debugEngine("PrinceEngine::loadLocation %d", locationNr);
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ SearchMan.remove(Common::String::format("%02d", _locationNr));
+
+ _locationNr = locationNr;
+ _debugger->_locationNr = locationNr;
+
+ _flags->setFlagValue(Flags::CURRROOM, _locationNr);
+ _interpreter->stopBg();
+
+ changeCursor(0);
+
+ const Common::String locationNrStr = Common::String::format("%02d", _locationNr);
+ debugEngine("loadLocation %s", locationNrStr.c_str());
+
+ PtcArchive *locationArchive = new PtcArchive();
+ if (!locationArchive->open(locationNrStr + "/databank.ptc"))
+ error("Can't open location %s", locationNrStr.c_str());
+
+ SearchMan.add(locationNrStr, locationArchive);
+
+ loadMusic(_locationNr);
+
+ // load location background, replace old one
+ Resource::loadResource(_roomBmp, "room", true);
+ if (_roomBmp->getSurface()) {
+ _sceneWidth = _roomBmp->getSurface()->w;
+ }
+
+ loadZoom(_zoomBitmap, kZoomBitmapLen, "zoom");
+ loadShadow(_shadowBitmap, kShadowBitmapSize, "shadow", "shadow2");
+ loadTrans(_transTable, "trans");
+ loadPath("path");
+
+ for (uint32 i = 0; i < _pscrList.size(); i++) {
+ delete _pscrList[i];
+ }
+ _pscrList.clear();
+ Resource::loadResource(_pscrList, "pscr.lst", false);
+
+ loadMobPriority("mobpri");
+
+ _mobList.clear();
+ if (getLanguage() == Common::DE_DEU) {
+ const Common::String mobLstName = Common::String::format("mob%02d.lst", _locationNr);
+ debug("name: %s", mobLstName.c_str());
+ Resource::loadResource(_mobList, mobLstName.c_str(), false);
+ } else {
+ Resource::loadResource(_mobList, "mob.lst", false);
+ }
+
+ _animList.clear();
+ Resource::loadResource(_animList, "anim.lst", false);
+
+ for (uint32 i = 0; i < _objList.size(); i++) {
+ delete _objList[i];
+ }
+ _objList.clear();
+ Resource::loadResource(_objList, "obj.lst", false);
+
+ _room->loadRoom(_script->getRoomOffset(_locationNr));
+
+ for (uint i = 0; i < _maskList.size(); i++) {
+ free(_maskList[i]._data);
+ }
+ _maskList.clear();
+ _script->loadAllMasks(_maskList, _room->_nak);
+
+ _picWindowX = 0;
+
+ _lightX = _script->getLightX(_locationNr);
+ _lightY = _script->getLightY(_locationNr);
+ setShadowScale(_script->getShadowScale(_locationNr));
+
+ for (uint i = 0; i < _mobList.size(); i++) {
+ _mobList[i]._visible = _script->getMobVisible(_room->_mobs, i);
+ }
+
+ _script->installObjects(_room->_obj);
+
+ freeAllNormAnims();
+
+ clearBackAnimList();
+ _script->installBackAnims(_backAnimList, _room->_backAnim);
+
+ _graph->makeShadowTable(70, _graph->_shadowTable70);
+ _graph->makeShadowTable(50, _graph->_shadowTable50);
+
+ _mainHero->freeOldMove();
+ _secondHero->freeOldMove();
+
+ _mainHero->scrollHero();
+
+ return true;
+}
+
+void PrinceEngine::setShadowScale(int32 shadowScale) {
+ shadowScale = 100 - shadowScale;
+ if (!shadowScale) {
+ _shadScaleValue = 10000;
+ } else {
+ _shadScaleValue = 10000 / shadowScale;
+ }
+}
+
+void PrinceEngine::plotShadowLinePoint(int x, int y, int color, void *data) {
+ PrinceEngine *vm = (PrinceEngine *)data;
+ WRITE_LE_UINT16(&vm->_shadowLine[vm->_shadLineLen * 4], x);
+ WRITE_LE_UINT16(&vm->_shadowLine[vm->_shadLineLen * 4 + 2], y);
+ vm->_shadLineLen++;
+}
+
+void PrinceEngine::changeCursor(uint16 curId) {
+ _debugger->_cursorNr = curId;
+ _mouseFlag = curId;
+ _flags->setFlagValue(Flags::MOUSEENABLED, curId);
+
+ const Graphics::Surface *curSurface = nullptr;
+
+ switch (curId) {
+ case 0:
+ CursorMan.showMouse(false);
+ _optionsFlag = 0;
+ _selectedMob = -1;
+ return;
+ case 1:
+ curSurface = _cursor1->getSurface();
+ break;
+ case 2:
+ curSurface = _cursor2;
+ break;
+ case 3:
+ curSurface = _cursor3->getSurface();
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ mousePos.x = CLIP(mousePos.x, (int16) 315, (int16) 639);
+ mousePos.y = CLIP(mousePos.y, (int16) 0, (int16) 170);
+ _system->warpMouse(mousePos.x, mousePos.y);
+ break;
+ }
+
+ CursorMan.replaceCursorPalette(_roomBmp->getPalette(), 0, 255);
+ CursorMan.replaceCursor(
+ curSurface->getBasePtr(0, 0),
+ curSurface->w, curSurface->h,
+ 0, 0,
+ 255, false,
+ &curSurface->format
+ );
+ CursorMan.showMouse(true);
+}
+
+void PrinceEngine::makeInvCursor(int itemNr) {
+ const Graphics::Surface *cur1Surface = _cursor1->getSurface();
+ int cur1W = cur1Surface->w;
+ int cur1H = cur1Surface->h;
+ const Common::Rect cur1Rect(0, 0, cur1W, cur1H);
+
+ const Graphics::Surface *itemSurface = _allInvList[itemNr].getSurface();
+ int itemW = itemSurface->w;
+ int itemH = itemSurface->h;
+
+ int cur2W = cur1W + itemW / 2;
+ int cur2H = cur1H + itemH / 2;
+
+ if (_cursor2 != nullptr) {
+ _cursor2->free();
+ delete _cursor2;
+ }
+ _cursor2 = new Graphics::Surface();
+ _cursor2->create(cur2W, cur2H, Graphics::PixelFormat::createFormatCLUT8());
+ Common::Rect cur2Rect(0, 0, cur2W, cur2H);
+ _cursor2->fillRect(cur2Rect, 255);
+ _cursor2->copyRectToSurface(*cur1Surface, 0, 0, cur1Rect);
+
+ const byte *src1 = (const byte *)itemSurface->getBasePtr(0, 0);
+ byte *dst1 = (byte *)_cursor2->getBasePtr(cur1W, cur1H);
+
+ if (itemH % 2) {
+ itemH--;
+ }
+ if (itemW % 2) {
+ itemW--;
+ }
+
+ for (int y = 0; y < itemH; y++) {
+ const byte *src2 = src1;
+ byte *dst2 = dst1;
+ if (y % 2 == 0) {
+ for (int x = 0; x < itemW; x++, src2++) {
+ if (x % 2 == 0) {
+ if (*src2) {
+ *dst2 = *src2;
+ } else {
+ *dst2 = 255;
+ }
+ dst2++;
+ }
+ }
+ dst1 += _cursor2->pitch;
+ }
+ src1 += itemSurface->pitch;
+ }
+}
+
+bool PrinceEngine::loadMusic(int musNumber) {
+ uint8 midiNumber = MusicPlayer::_musRoomTable[musNumber];
+ if (midiNumber) {
+ if (midiNumber != 100) {
+ if (_currentMidi != midiNumber) {
+ _currentMidi = midiNumber;
+ const char *musName = MusicPlayer::_musTable[_currentMidi];
+ _midiPlayer->loadMidi(musName);
+ }
+ }
+ } else {
+ stopMusic();
+ }
+ return true;
+}
+
+void PrinceEngine::stopMusic() {
+ if (_midiPlayer->isPlaying()) {
+ _midiPlayer->stop();
+ }
+}
+
+bool PrinceEngine::playNextFLCFrame() {
+ if (!_flicPlayer.isVideoLoaded())
+ return false;
+
+ const Graphics::Surface *s = _flicPlayer.decodeNextFrame();
+ if (s) {
+ _graph->drawTransparentSurface(_graph->_frontScreen, 0, 0, s, 255);
+ _graph->change();
+ _flcFrameSurface = s;
+ } else if (_flicLooped) {
+ _flicPlayer.rewind();
+ playNextFLCFrame();
+ } else if (_flcFrameSurface) {
+ _graph->drawTransparentSurface(_graph->_frontScreen, 0, 0, _flcFrameSurface, 255);
+ _graph->change();
+ }
+
+ return true;
+}
+
+void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
+ if (_audioStream[sampleId]) {
+ if (_mixer->isSoundIDActive(sampleId)) {
+ return;
+ }
+ _audioStream[sampleId]->rewind();
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ }
+}
+
+void PrinceEngine::stopSample(uint16 sampleId) {
+ _mixer->stopID(sampleId);
+}
+
+void PrinceEngine::stopAllSamples() {
+ _mixer->stopAll();
+}
+
+void PrinceEngine::freeSample(uint16 sampleId) {
+ stopSample(sampleId);
+ if (_audioStream[sampleId] != nullptr) {
+ delete _audioStream[sampleId];
+ _audioStream[sampleId] = nullptr;
+ }
+}
+
+void PrinceEngine::freeAllSamples() {
+ for (int sampleId = 0; sampleId < kMaxSamples; sampleId++) {
+ freeSample(sampleId);
+ }
+}
+
+bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
+ // FIXME: This is just a workaround streamName is a path
+ // SOUND\\SCIERKA1.WAV for now only last path component is used
+ Common::String normalizedPath = lastPathComponent(streamName, '\\');
+
+ // WALKAROUND: Wrong name in script, not existing sound in data files
+ if (!normalizedPath.compareTo("9997BEKA.WAV")) {
+ return 0;
+ }
+
+ debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
+
+ freeSample(sampleSlot);
+ Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(normalizedPath);
+ if (sampleStream == nullptr) {
+ delete sampleStream;
+ error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
+ }
+ _audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
+ delete sampleStream;
+ return true;
+}
+
+bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
+ debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
+
+ if (slot >= kMaxTexts) {
+ error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
+ return false;
+ }
+
+ freeSample(sampleSlot);
+ Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(streamName);
+ if (sampleStream == nullptr) {
+ debug("Can't open %s", streamName.c_str());
+ return false;
+ }
+
+ uint32 id = sampleStream->readUint32LE();
+ if (id != MKTAG('F', 'F', 'I', 'R')) {
+ error("It's not RIFF file %s", streamName.c_str());
+ return false;
+ }
+
+ sampleStream->skip(0x20);
+ id = sampleStream->readUint32LE();
+ if (id != MKTAG('a', 't', 'a', 'd')) {
+ error("No data section in %s id %04x", streamName.c_str(), id);
+ return false;
+ }
+
+ id = sampleStream->readUint32LE();
+ debugEngine("SetVoice slot %d time %04x", slot, id);
+ id <<= 3;
+ id /= 22050;
+ id += 2;
+
+ _textSlots[slot]._time = id;
+ if (!slot) {
+ _mainHero->_talkTime = id;
+ } else if (slot == 1) {
+ _secondHero->_talkTime = id;
+ }
+
+ debugEngine("SetVoice slot %d time %04x", slot, id);
+ sampleStream->seek(SEEK_SET);
+ _audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
+ delete sampleStream;
+ return true;
+}
+
+void PrinceEngine::setVoice(uint16 slot, uint32 sampleSlot, uint16 flag) {
+ Common::String sampleName;
+ uint32 currentString = _interpreter->getCurrentString();
+
+ if (currentString >= 80000) {
+ uint32 nr = currentString - 80000;
+ sampleName = Common::String::format("%02d0%02d-%02d.WAV", nr / 100, nr % 100, flag);
+ } else if (currentString >= 70000) {
+ sampleName = Common::String::format("inv%02d-01.WAV", currentString - 70000);
+ } else if (currentString >= 60000) {
+ sampleName = Common::String::format("M%04d-%02d.WAV", currentString - 60000, flag);
+ } else if (currentString >= 2000) {
+ return;
+ } else if (flag >= 100) {
+ sampleName = Common::String::format("%03d-%03d.WAV", currentString, flag);
+ } else {
+ sampleName = Common::String::format("%03d-%02d.WAV", currentString, flag);
+ }
+
+ loadVoice(slot, sampleSlot, sampleName);
+}
+
+bool PrinceEngine::loadAnim(uint16 animNr, bool loop) {
+ Common::String streamName = Common::String::format("AN%02d", animNr);
+ Common::SeekableReadStream *flicStream = SearchMan.createReadStreamForMember(streamName);
+
+ if (!flicStream) {
+ error("Can't open %s", streamName.c_str());
+ return false;
+ }
+
+ if (!_flicPlayer.loadStream(flicStream)) {
+ error("Can't load flic stream %s", streamName.c_str());
+ }
+
+ debugEngine("%s loaded", streamName.c_str());
+ _flicLooped = loop;
+ _flicPlayer.start();
+ playNextFLCFrame();
+ return true;
+}
+
+bool PrinceEngine::loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+ if (stream->read(zoomBitmap, dataSize) != dataSize) {
+ free(zoomBitmap);
+ delete stream;
+ return false;
+ }
+ delete stream;
+ return true;
+}
+
+bool PrinceEngine::loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName1);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+
+ if (stream->read(shadowBitmap, dataSize) != dataSize) {
+ free(shadowBitmap);
+ delete stream;
+ return false;
+ }
+
+ Common::SeekableReadStream *stream2 = SearchMan.createReadStreamForMember(resourceName2);
+ if (!stream2) {
+ delete stream;
+ delete stream2;
+ return false;
+ }
+
+ byte *shadowBitmap2 = shadowBitmap + dataSize;
+ if (stream2->read(shadowBitmap2, dataSize) != dataSize) {
+ free(shadowBitmap);
+ delete stream;
+ delete stream2;
+ return false;
+ }
+
+ delete stream;
+ delete stream2;
+ return true;
+}
+
+bool PrinceEngine::loadTrans(byte *transTable, const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ for (int i = 0; i < 256; i++) {
+ for (int j = 0; j < 256; j++) {
+ transTable[i * 256 + j] = j;
+ }
+ }
+ return true;
+ }
+ if (stream->read(transTable, kTransTableSize) != kTransTableSize) {
+ delete stream;
+ return false;
+ }
+ delete stream;
+ return true;
+}
+
+bool PrinceEngine::loadPath(const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+ if (stream->read(_roomPathBitmap, kPathBitmapLen) != kPathBitmapLen) {
+ delete stream;
+ return false;
+ }
+ delete stream;
+ return true;
+}
+
+bool PrinceEngine::loadAllInv() {
+ for (int i = 0; i < kMaxInv; i++) {
+ InvItem tempInvItem;
+
+ const Common::String invStreamName = Common::String::format("INV%02d", i);
+ Common::SeekableReadStream *invStream = SearchMan.createReadStreamForMember(invStreamName);
+ if (!invStream) {
+ delete invStream;
+ return true;
+ }
+
+ tempInvItem._x = invStream->readUint16LE();
+ tempInvItem._y = invStream->readUint16LE();
+ int width = invStream->readUint16LE();
+ int height = invStream->readUint16LE();
+ tempInvItem._surface = new Graphics::Surface();
+ tempInvItem._surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int h = 0; h < tempInvItem._surface->h; h++) {
+ invStream->read(tempInvItem._surface->getBasePtr(0, h), tempInvItem._surface->w);
+ }
+
+ _allInvList.push_back(tempInvItem);
+ delete invStream;
+ }
+
+ return true;
+}
+
+bool PrinceEngine::loadMobPriority(const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+
+ _mobPriorityList.clear();
+ uint mobId;
+ while (1) {
+ mobId = stream->readUint32LE();
+ if (mobId == 0xFFFFFFFF) {
+ break;
+ }
+ _mobPriorityList.push_back(mobId);
+ }
+ delete stream;
+ return true;
+}
+
+void PrinceEngine::keyHandler(Common::Event event) {
+ uint16 nChar = event.kbd.keycode;
+ switch (nChar) {
+ case Common::KEYCODE_d:
+ if (event.kbd.hasFlags(Common::KBD_CTRL)) {
+ getDebugger()->attach();
+ }
+ break;
+ case Common::KEYCODE_z:
+ if (_flags->getFlagValue(Flags::POWERENABLED)) {
+ _flags->setFlagValue(Flags::MBFLAG, 1);
+ }
+ break;
+ case Common::KEYCODE_x:
+ if (_flags->getFlagValue(Flags::POWERENABLED)) {
+ _flags->setFlagValue(Flags::MBFLAG, 2);
+ }
+ break;
+ case Common::KEYCODE_ESCAPE:
+ _flags->setFlagValue(Flags::ESCAPED2, 1);
+ break;
+ }
+}
+
+int PrinceEngine::getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY) {
+
+ Common::Point pointPos(posX, posY);
+
+ int mobListSize;
+ if (usePriorityList) {
+ mobListSize = _mobPriorityList.size();
+ } else {
+ mobListSize = mobList.size();
+ }
+
+ for (int mobNumber = 0; mobNumber < mobListSize; mobNumber++) {
+ Mob *mob = nullptr;
+ if (usePriorityList) {
+ mob = &mobList[_mobPriorityList[mobNumber]];
+ } else {
+ mob = &mobList[mobNumber];
+ }
+
+ if (mob->_visible) {
+ continue;
+ }
+
+ int type = mob->_type & 7;
+ switch (type) {
+ case 0:
+ case 1:
+ //normal_mob
+ if (!mob->_rect.contains(pointPos)) {
+ continue;
+ }
+ break;
+ case 3:
+ //mob_obj
+ if (mob->_mask < kMaxObjects) {
+ int nr = _objSlot[mob->_mask];
+ if (nr != 0xFF) {
+ Object &obj = *_objList[nr];
+ Common::Rect objectRect(obj._x, obj._y, obj._x + obj._width, obj._y + obj._height);
+ if (objectRect.contains(pointPos)) {
+ Graphics::Surface *objSurface = obj.getSurface();
+ byte *pixel = (byte *)objSurface->getBasePtr(posX - obj._x, posY - obj._y);
+ if (*pixel != 255) {
+ break;
+ }
+ }
+ }
+ }
+ continue;
+ break;
+ case 2:
+ case 5:
+ //check_ba_mob
+ if (!_backAnimList[mob->_mask].backAnims.empty()) {
+ int currentAnim = _backAnimList[mob->_mask]._seq._currRelative;
+ Anim &backAnim = _backAnimList[mob->_mask].backAnims[currentAnim];
+ if (backAnim._animData != nullptr) {
+ if (!backAnim._state) {
+ Common::Rect backAnimRect(backAnim._currX, backAnim._currY, backAnim._currX + backAnim._currW, backAnim._currY + backAnim._currH);
+ if (backAnimRect.contains(pointPos)) {
+ int phase = backAnim._showFrame;
+ int phaseFrameIndex = backAnim._animData->getPhaseFrameIndex(phase);
+ Graphics::Surface *backAnimSurface = backAnim._animData->getFrame(phaseFrameIndex);
+ byte pixel = *(byte *)backAnimSurface->getBasePtr(posX - backAnim._currX, posY - backAnim._currY);
+ if (pixel != 255) {
+ if (type == 5) {
+ if (mob->_rect.contains(pointPos)) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ continue;
+ break;
+ default:
+ //not_part_ba
+ continue;
+ break;
+ }
+
+ if (usePriorityList) {
+ return _mobPriorityList[mobNumber];
+ } else {
+ return mobNumber;
+ }
+ }
+ return -1;
+}
+
+int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList) {
+ if (_mouseFlag == 0 || _mouseFlag == 3) {
+ return -1;
+ }
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ int mobNumber = getMob(mobList, usePriorityList, mousePos.x + _picWindowX, mousePos.y);
+
+ if (mobNumber != -1) {
+ Common::String mobName = mobList[mobNumber]._name;
+
+ if (getLanguage() == Common::DE_DEU) {
+ for (uint i = 0; i < mobName.size(); i++) {
+ switch (mobName[i]) {
+ case '\xc4':
+ mobName.setChar('\x83', i);
+ break;
+ case '\xd6':
+ mobName.setChar('\x84', i);
+ break;
+ case '\xdc':
+ mobName.setChar('\x85', i);
+ break;
+ case '\xdf':
+ mobName.setChar('\x7f', i);
+ break;
+ case '\xe4':
+ mobName.setChar('\x80', i);
+ break;
+ case '\xf6':
+ mobName.setChar('\x81', i);
+ break;
+ case '\xfc':
+ mobName.setChar('\x82', i);
+ break;
+ }
+ }
+ }
+
+ uint16 textW = getTextWidth(mobName.c_str());
+
+ uint16 x = mousePos.x - textW / 2;
+ if (x > screen->w) {
+ x = 0;
+ }
+
+ if (x + textW > screen->w) {
+ x = screen->w - textW;
+ }
+
+ uint16 y = mousePos.y - _font->getFontHeight();
+ if (y > screen->h) {
+ y = _font->getFontHeight() - 2;
+ }
+
+ _font->drawString(screen, mobName, x, y, screen->w, 216);
+ }
+
+ return mobNumber;
+}
+
+void PrinceEngine::printAt(uint32 slot, uint8 color, char *s, uint16 x, uint16 y) {
+ debugC(1, DebugChannel::kEngine, "PrinceEngine::printAt slot %d, color %d, x %02d, y %02d, str %s", slot, color, x, y, s);
+
+ if (getLanguage() == Common::DE_DEU)
+ correctStringDEU(s);
+
+ Text &text = _textSlots[slot];
+ text._str = s;
+ text._x = x;
+ text._y = y;
+ text._color = color;
+ int lines = calcTextLines(s);
+ text._time = calcTextTime(lines);
+}
+
+int PrinceEngine::calcTextLines(const char *s) {
+ int lines = 1;
+ while (*s) {
+ if (*s == '\n') {
+ lines++;
+ }
+ s++;
+ }
+ return lines;
+}
+
+int PrinceEngine::calcTextTime(int numberOfLines) {
+ return numberOfLines * 30;
+}
+
+void PrinceEngine::correctStringDEU(char *s) {
+ while (*s) {
+ switch (*s) {
+ case '\xc4':
+ *s = '\x83';
+ break;
+ case '\xd6':
+ *s = '\x84';
+ break;
+ case '\xdc':
+ *s = '\x85';
+ break;
+ case '\xdf':
+ *s = '\x7f';
+ break;
+ case '\xe4':
+ *s = '\x80';
+ break;
+ case '\xf6':
+ *s = '\x81';
+ break;
+ case '\xfc':
+ *s = '\x82';
+ break;
+ }
+ s++;
+ }
+}
+
+uint32 PrinceEngine::getTextWidth(const char *s) {
+ uint16 textW = 0;
+ while (*s) {
+ textW += _font->getCharWidth(*s) + _font->getKerningOffset(0, 0);
+ s++;
+ }
+ return textW;
+}
+
+void PrinceEngine::showTexts(Graphics::Surface *screen) {
+ for (uint32 slot = 0; slot < kMaxTexts; slot++) {
+
+ if (_showInventoryFlag && slot) {
+ // only slot 0 for inventory
+ break;
+ }
+
+ Text& text = _textSlots[slot];
+ if (!text._str && !text._time) {
+ continue;
+ }
+
+ int x = text._x;
+ int y = text._y;
+
+ if (!_showInventoryFlag) {
+ x -= _picWindowX;
+ y -= _picWindowY;
+ }
+
+ Common::Array<Common::String> lines;
+ _font->wordWrapText(text._str, _graph->_frontScreen->w, lines);
+
+ int wideLine = 0;
+ for (uint i = 0; i < lines.size(); i++) {
+ int textLen = getTextWidth(lines[i].c_str());
+ if (textLen > wideLine) {
+ wideLine = textLen;
+ }
+ }
+
+ int leftBorderText = 6;
+ if (x + wideLine / 2 > kNormalWidth - leftBorderText) {
+ x = kNormalWidth - leftBorderText - wideLine / 2;
+ }
+
+ if (x - wideLine / 2 < leftBorderText) {
+ x = leftBorderText + wideLine / 2;
+ }
+
+ int textSkip = 2;
+ for (uint i = 0; i < lines.size(); i++) {
+ int drawX = x - getTextWidth(lines[i].c_str()) / 2;
+ int drawY = y - 10 - (lines.size() - i) * (_font->getFontHeight() - textSkip);
+ if (drawX < 0) {
+ drawX = 0;
+ }
+ if (drawY < 0) {
+ drawY = 0;
+ }
+ _font->drawString(screen, lines[i], drawX, drawY, screen->w, text._color);
+ }
+
+ text._time--;
+ if (!text._time) {
+ text._str = nullptr;
+ }
+ }
+}
+
+bool PrinceEngine::spriteCheck(int sprWidth, int sprHeight, int destX, int destY) {
+ destX -= _picWindowX;
+ destY -= _picWindowY;
+
+ // if x1 is on visible part of screen
+ if (destX < 0) {
+ if (destX + sprWidth < 1) {
+ //x2 is negative - out of window
+ return false;
+ }
+ }
+ // if x1 is outside of screen on right side
+ if (destX >= kNormalWidth) {
+ return false;
+ }
+
+ if (destY < 0) {
+ if (destY + sprHeight < 1) {
+ //y2 is negative - out of window
+ return false;
+ }
+ }
+ if (destY >= kNormalHeight) {
+ return false;
+ }
+
+ return true;
+}
+
+// CheckNak
+void PrinceEngine::checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z) {
+ int x2 = x1 + sprWidth - 1;
+ int y2 = y1 + sprHeight - 1;
+ if (x1 < 0) {
+ x1 = 0;
+ }
+ for (uint i = 0; i < _maskList.size(); i++) {
+ if (!_maskList[i]._state && !_maskList[i]._flags) {
+ if (_maskList[i]._z > z) {
+ if (_maskList[i]._x1 <= x2 && _maskList[i]._x2 >= x1) {
+ if (_maskList[i]._y1 <= y2 && _maskList[i]._y2 >= y1) {
+ _maskList[i]._state = 1;
+ }
+ }
+ }
+ }
+ }
+}
+
+// ClsNak
+void PrinceEngine::clsMasks() {
+ for (uint i = 0; i < _maskList.size(); i++) {
+ if (_maskList[i]._state) {
+ _maskList[i]._state = 0;
+ }
+ }
+}
+
+// InsertNakladki
+void PrinceEngine::insertMasks(Graphics::Surface *originalRoomSurface) {
+ for (uint i = 0; i < _maskList.size(); i++) {
+ if (_maskList[i]._state) {
+ if (_maskList[i]._data != nullptr) {
+ showMask(i, originalRoomSurface);
+ } else {
+ error("insertMasks() - Wrong mask data- nr %d", i);
+ }
+ }
+ }
+}
+
+// ShowNak
+void PrinceEngine::showMask(int maskNr, Graphics::Surface *originalRoomSurface) {
+ if (!_maskList[maskNr]._flags) {
+ if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) {
+ int destX = _maskList[maskNr]._x1 - _picWindowX;
+ int destY = _maskList[maskNr]._y1 - _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = _maskList[maskNr]._z;
+ newDrawNode.width = _maskList[maskNr]._width;
+ newDrawNode.height = _maskList[maskNr]._height;
+ newDrawNode.s = nullptr;
+ newDrawNode.originalRoomSurface = originalRoomSurface;
+ newDrawNode.data = _maskList[maskNr].getMask();
+ newDrawNode.drawFunction = &_graph->drawMaskDrawNode;
+ _drawNodeList.push_back(newDrawNode);
+ }
+ }
+}
+
+void PrinceEngine::showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ) {
+ if (spriteCheck(spriteSurface->w, spriteSurface->h, destX, destY)) {
+ destX -= _picWindowX;
+ destY -= _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = destZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.s = spriteSurface;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = _transTable;
+ newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
+ _drawNodeList.push_back(newDrawNode);
+ }
+}
+
+void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ) {
+ if (spriteCheck(shadowSurface->w, shadowSurface->h, destX, destY)) {
+ destX -= _picWindowX;
+ destY -= _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = destZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.s = shadowSurface;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = _graph->_shadowTable70;
+ newDrawNode.drawFunction = &_graph->drawAsShadowDrawNode;
+ _drawNodeList.push_back(newDrawNode);
+ }
+}
+
+void PrinceEngine::showAnim(Anim &anim) {
+ //ShowFrameCode
+ //ShowAnimFrame
+ int phase = anim._showFrame;
+ int phaseFrameIndex = anim._animData->getPhaseFrameIndex(phase);
+ int x = anim._x + anim._animData->getPhaseOffsetX(phase);
+ int y = anim._y + anim._animData->getPhaseOffsetY(phase);
+ int animFlag = anim._flags;
+ int checkMaskFlag = (animFlag & 1);
+ int maxFrontFlag = (animFlag & 2);
+ int specialZFlag = anim._nextAnim;
+ int z = anim._nextAnim;
+ Graphics::Surface *animSurface = anim._animData->getFrame(phaseFrameIndex);
+ int frameWidth = animSurface->w;
+ int frameHeight = animSurface->h;
+ int shadowZ = 0;
+
+ if (checkMaskFlag) {
+ if (!anim._nextAnim) {
+ z = y + frameHeight - 1;
+ }
+ checkMasks(x, y, frameWidth, frameHeight, z);
+ }
+
+ if (specialZFlag) {
+ z = specialZFlag;
+ } else if (maxFrontFlag) {
+ z = kMaxPicHeight + 1;
+ } else {
+ z = y + frameHeight - 1;
+ }
+ shadowZ = z;
+
+ anim._currX = x;
+ anim._currY = y;
+ anim._currW = frameWidth;
+ anim._currH = frameHeight;
+ showSprite(animSurface, x, y, z);
+
+ // make_special_shadow
+ if ((anim._flags & 0x80)) {
+ if (animSurface) {
+ DrawNode newDrawNode;
+ newDrawNode.posX = x;
+ newDrawNode.posY = y + animSurface->h - anim._shadowBack;
+ newDrawNode.posZ = Hero::kHeroShadowZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.scaleValue = _scaleValue;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = this;
+ newDrawNode.drawFunction = &Hero::showHeroShadow;
+ newDrawNode.s = animSurface;
+ _drawNodeList.push_back(newDrawNode);
+ }
+ }
+
+ //ShowFrameCodeShadow
+ //ShowAnimFrameShadow
+ if (anim._shadowData != nullptr) {
+ int shadowPhaseFrameIndex = anim._shadowData->getPhaseFrameIndex(phase);
+ int shadowX = anim._shadowData->getBaseX() + anim._shadowData->getPhaseOffsetX(phase);
+ int shadowY = anim._shadowData->getBaseY() + anim._shadowData->getPhaseOffsetY(phase);
+ Graphics::Surface *shadowSurface = anim._shadowData->getFrame(shadowPhaseFrameIndex);
+ int shadowFrameWidth = shadowSurface->w;
+ int shadowFrameHeight = shadowSurface->h;
+
+ if (checkMaskFlag) {
+ checkMasks(shadowX, shadowY, shadowFrameWidth, shadowFrameHeight, shadowY + shadowFrameWidth - 1);
+ }
+
+ if (!shadowZ) {
+ if (maxFrontFlag) {
+ shadowZ = kMaxPicHeight + 1;
+ } else {
+ shadowZ = shadowY + shadowFrameWidth - 1;
+ }
+ }
+ showSpriteShadow(shadowSurface, shadowX, shadowY, shadowZ);
+ }
+}
+
+void PrinceEngine::showNormAnims() {
+ for (int i = 0; i < kMaxNormAnims; i++) {
+ Anim &anim = _normAnimList[i];
+ if (anim._animData != nullptr) {
+ int phaseCount = anim._animData->getPhaseCount();
+ if (!anim._state) {
+ if (anim._frame == anim._lastFrame - 1) {
+ if (anim._loopType) {
+ if (anim._loopType == 1) {
+ anim._frame = anim._loopFrame;
+ } else {
+ continue;
+ }
+ }
+ } else {
+ anim._frame++;
+ }
+ anim._showFrame = anim._frame;
+ if (anim._showFrame >= phaseCount) {
+ anim._showFrame = phaseCount - 1;
+ }
+ showAnim(anim);
+ }
+ }
+ }
+}
+
+void PrinceEngine::setBackAnim(Anim &backAnim) {
+ int start = backAnim._basaData._start;
+ if (start != -1) {
+ backAnim._frame = start;
+ backAnim._showFrame = start;
+ backAnim._loopFrame = start;
+ }
+ int end = backAnim._basaData._end;
+ if (end != -1) {
+ backAnim._lastFrame = end;
+ }
+ backAnim._state = 0;
+}
+
+void PrinceEngine::showBackAnims() {
+ for (uint i = 0; i < kMaxBackAnims; i++) {
+ BAS &seq = _backAnimList[i]._seq;
+ int activeSubAnim = seq._currRelative;
+ if (!_backAnimList[i].backAnims.empty()) {
+ if (_backAnimList[i].backAnims[activeSubAnim]._animData != nullptr) {
+ if (!_backAnimList[i].backAnims[activeSubAnim]._state) {
+ seq._counter++;
+ if (seq._type == 2) {
+ if (!seq._currRelative) {
+ if (seq._counter >= seq._data) {
+ if (seq._anims > 2) {
+ seq._currRelative = _randomSource.getRandomNumber(seq._anims - 2) + 1;
+ activeSubAnim = seq._currRelative;
+ seq._current = _backAnimList[i].backAnims[activeSubAnim]._basaData._num;
+ }
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ seq._counter = 0;
+ }
+ }
+ }
+
+ if (seq._type == 3) {
+ if (!seq._currRelative) {
+ if (seq._counter < seq._data2) {
+ continue;
+ } else {
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ }
+ }
+ }
+
+ if (_backAnimList[i].backAnims[activeSubAnim]._frame == _backAnimList[i].backAnims[activeSubAnim]._lastFrame - 1) {
+ _backAnimList[i].backAnims[activeSubAnim]._frame = _backAnimList[i].backAnims[activeSubAnim]._loopFrame;
+ switch (seq._type) {
+ case 1:
+ if (seq._anims > 1) {
+ int rnd;
+ do {
+ rnd = _randomSource.getRandomNumber(seq._anims - 1);
+ } while (rnd == seq._currRelative);
+ seq._currRelative = rnd;
+ seq._current = _backAnimList[i].backAnims[rnd]._basaData._num;
+ activeSubAnim = rnd;
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ seq._counter = 0;
+ }
+ break;
+ case 2:
+ if (seq._currRelative) {
+ seq._currRelative = 0;
+ seq._current = _backAnimList[i].backAnims[0]._basaData._num;
+ activeSubAnim = 0;
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ seq._counter = 0;
+ }
+ break;
+ case 3:
+ seq._currRelative = 0;
+ seq._current = _backAnimList[i].backAnims[0]._basaData._num;
+ seq._counter = 0;
+ seq._data2 = _randomSource.getRandomNumber(seq._data - 1);
+ continue; // for bug in original game
+ break;
+ }
+ } else {
+ _backAnimList[i].backAnims[activeSubAnim]._frame++;
+ }
+ _backAnimList[i].backAnims[activeSubAnim]._showFrame = _backAnimList[i].backAnims[activeSubAnim]._frame;
+ showAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ }
+ }
+ }
+ }
+}
+
+void PrinceEngine::removeSingleBackAnim(int slot) {
+ if (!_backAnimList[slot].backAnims.empty()) {
+ for (uint j = 0; j < _backAnimList[slot].backAnims.size(); j++) {
+ if (_backAnimList[slot].backAnims[j]._animData != nullptr) {
+ delete _backAnimList[slot].backAnims[j]._animData;
+ _backAnimList[slot].backAnims[j]._animData = nullptr;
+ }
+ if (_backAnimList[slot].backAnims[j]._shadowData != nullptr) {
+ delete _backAnimList[slot].backAnims[j]._shadowData;
+ _backAnimList[slot].backAnims[j]._shadowData = nullptr;
+ }
+ }
+ _backAnimList[slot].backAnims.clear();
+ _backAnimList[slot]._seq._currRelative = 0;
+ }
+}
+
+void PrinceEngine::clearBackAnimList() {
+ for (int i = 0; i < kMaxBackAnims; i++) {
+ removeSingleBackAnim(i);
+ }
+}
+
+void PrinceEngine::grabMap() {
+ _graph->_frontScreen->copyFrom(*_roomBmp->getSurface());
+ showObjects();
+ runDrawNodes();
+ _graph->_mapScreen->copyFrom(*_graph->_frontScreen);
+}
+
+void PrinceEngine::initZoomIn(int slot) {
+ freeZoomObject(slot);
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *zoomSource = object->getSurface();
+ if (zoomSource != nullptr) {
+ object->_flags |= 0x8000;
+ object->_zoomSurface = new Graphics::Surface();
+ object->_zoomSurface->create(zoomSource->w, zoomSource->h, Graphics::PixelFormat::createFormatCLUT8());
+ object->_zoomSurface->fillRect(Common::Rect(zoomSource->w, zoomSource->h), 0xFF);
+ object->_zoomTime = 20;
+ }
+ }
+}
+
+void PrinceEngine::initZoomOut(int slot) {
+ freeZoomObject(slot);
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *zoomSource = object->getSurface();
+ if (zoomSource != nullptr) {
+ object->_flags |= 0x4000;
+ object->_zoomSurface = new Graphics::Surface();
+ object->_zoomSurface->copyFrom(*zoomSource);
+ object->_zoomTime = 10;
+ }
+ }
+}
+
+void PrinceEngine::doZoomIn(int slot) {
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *orgSurface = object->getSurface();
+ if (orgSurface != nullptr) {
+ byte *src1 = (byte *)orgSurface->getBasePtr(0, 0);
+ byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
+ int x = 0;
+ int surfaceHeight = orgSurface->h;
+ for (int y = 0; y < surfaceHeight; y++) {
+ byte *src2 = src1;
+ byte *dst2 = dst1;
+ int w = orgSurface->w - x;
+ src2 += x;
+ dst2 += x;
+ while (w > 0) {
+ int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
+ if (randVal < w) {
+ *(dst2 + randVal) = *(src2 + randVal);
+ src2 += zoomInStep;
+ dst2 += zoomInStep;
+ } else if (y + 1 != surfaceHeight) {
+ *(dst1 + orgSurface->pitch + randVal - w) = *(src1 + orgSurface->pitch + randVal - w);
+ }
+ w -= zoomInStep;
+ }
+ x = -1 * w;
+ src1 += orgSurface->pitch;
+ dst1 += orgSurface->pitch;
+ }
+ }
+ }
+}
+
+void PrinceEngine::doZoomOut(int slot) {
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *orgSurface = object->getSurface();
+ if (orgSurface != nullptr) {
+ byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
+ int x = 0;
+ int surfaceHeight = orgSurface->h;
+ for (int y = 0; y < surfaceHeight; y++) {
+ byte *dst2 = dst1;
+ int w = orgSurface->w - x;
+ dst2 += x;
+ while (w > 0) {
+ int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
+ if (randVal < w) {
+ *(dst2 + randVal) = 255;
+ dst2 += zoomInStep;
+ } else if (y + 1 != surfaceHeight) {
+ *(dst1 + orgSurface->pitch + randVal - w) = 255;
+ }
+ w -= zoomInStep;
+ }
+ x = -1 * w;
+ dst1 += orgSurface->pitch;
+ }
+ }
+ }
+}
+
+void PrinceEngine::freeZoomObject(int slot) {
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ if (object->_zoomSurface != nullptr) {
+ object->_zoomSurface->free();
+ delete object->_zoomSurface;
+ object->_zoomSurface = nullptr;
+ }
+ }
+}
+
+void PrinceEngine::showObjects() {
+ for (int i = 0; i < kMaxObjects; i++) {
+ int nr = _objSlot[i];
+ if (nr != 0xFF) {
+ Graphics::Surface *objSurface = nullptr;
+ if ((_objList[nr]->_flags & 0x8000)) {
+ _objList[nr]->_zoomTime--;
+ if (!_objList[nr]->_zoomTime) {
+ freeZoomObject(nr);
+ _objList[nr]->_flags &= 0x7FFF;
+ objSurface = _objList[nr]->getSurface();
+ } else {
+ doZoomIn(nr);
+ objSurface = _objList[nr]->_zoomSurface;
+ }
+ } else if ((_objList[nr]->_flags & 0x4000)) {
+ _objList[nr]->_zoomTime--;
+ if (!_objList[nr]->_zoomTime) {
+ freeZoomObject(nr);
+ _objList[nr]->_flags &= 0xBFFF;
+ objSurface = _objList[nr]->getSurface();
+ } else {
+ doZoomOut(nr);
+ objSurface = _objList[nr]->_zoomSurface;
+ }
+ } else {
+ objSurface = _objList[nr]->getSurface();
+ }
+
+ if (objSurface != nullptr) {
+ if (spriteCheck(objSurface->w, objSurface->h, _objList[nr]->_x, _objList[nr]->_y)) {
+ int destX = _objList[nr]->_x - _picWindowX;
+ int destY = _objList[nr]->_y - _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = _objList[nr]->_z;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.s = objSurface;
+ newDrawNode.originalRoomSurface = nullptr;
+ if ((_objList[nr]->_flags & 0x2000)) {
+ newDrawNode.data = nullptr;
+ newDrawNode.drawFunction = &_graph->drawBackSpriteDrawNode;
+ } else {
+ newDrawNode.data = _transTable;
+ if (_flags->getFlagValue(Flags::NOANTIALIAS)) {
+ newDrawNode.drawFunction = &_graph->drawTransparentDrawNode;
+ } else {
+ newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
+ }
+ }
+ _drawNodeList.push_back(newDrawNode);
+ }
+
+ if ((_objList[nr]->_flags & 1)) {
+ checkMasks(_objList[nr]->_x, _objList[nr]->_y, objSurface->w, objSurface->h, _objList[nr]->_z);
+ }
+ }
+ }
+ }
+}
+
+void PrinceEngine::showParallax() {
+ if (!_pscrList.empty()) {
+ for (uint i = 0; i < _pscrList.size(); i++) {
+ Graphics::Surface *pscrSurface = _pscrList[i]->getSurface();
+ if (pscrSurface != nullptr) {
+ int x = _pscrList[i]->_x - (_pscrList[i]->_step * _picWindowX / 4);
+ int y = _pscrList[i]->_y;
+ int z = PScr::kPScrZ;
+ if (spriteCheck(pscrSurface->w, pscrSurface->h, x, y)) {
+ showSprite(pscrSurface, x, y, z);
+ }
+ }
+ }
+ }
+}
+
+bool PrinceEngine::compareDrawNodes(DrawNode d1, DrawNode d2) {
+ if (d1.posZ < d2.posZ) {
+ return true;
+ }
+ return false;
+}
+
+void PrinceEngine::runDrawNodes() {
+ Common::sort(_drawNodeList.begin(), _drawNodeList.end(), compareDrawNodes);
+
+ for (uint i = 0; i < _drawNodeList.size(); i++) {
+ (*_drawNodeList[i].drawFunction)(_graph->_frontScreen, &_drawNodeList[i]);
+ }
+ _graph->change();
+}
+
+void PrinceEngine::drawScreen() {
+ if (!_showInventoryFlag || _inventoryBackgroundRemember) {
+ clsMasks();
+
+ _mainHero->showHero();
+ _mainHero->scrollHero();
+ _mainHero->drawHero();
+
+ _secondHero->showHero();
+ _secondHero->_drawX -= _picWindowX;
+ _secondHero->drawHero();
+
+ const Graphics::Surface *roomSurface;
+ if (_locationNr != 50) {
+ roomSurface = _roomBmp->getSurface();
+ } else {
+ roomSurface = _graph->_mapScreen;
+ }
+ Graphics::Surface visiblePart;
+ if (roomSurface) {
+ visiblePart = roomSurface->getSubArea(Common::Rect(_picWindowX, 0, roomSurface->w, roomSurface->h));
+ _graph->draw(_graph->_frontScreen, &visiblePart);
+ }
+
+ showBackAnims();
+
+ showNormAnims();
+
+ playNextFLCFrame();
+
+ showObjects();
+
+ if (roomSurface) {
+ insertMasks(&visiblePart);
+ }
+
+ showParallax();
+
+ runDrawNodes();
+
+ _drawNodeList.clear();
+
+ if (!_inventoryBackgroundRemember && !_dialogFlag) {
+ if (!_optionsFlag) {
+ _selectedMob = checkMob(_graph->_frontScreen, _mobList, true);
+ }
+ showTexts(_graph->_frontScreen);
+ checkOptions();
+ } else {
+ _inventoryBackgroundRemember = false;
+ }
+
+ showPower();
+
+ getDebugger()->onFrame();
+
+ } else {
+ displayInventory();
+ }
+}
+
+void PrinceEngine::blackPalette() {
+ byte *paletteBackup = (byte *)malloc(256 * 3);
+ byte *blackPalette1 = (byte *)malloc(256 * 3);
+
+ int fadeStep = kFadeStep - 1;
+ for (int i = 0; i < kFadeStep; i++) {
+ _system->getPaletteManager()->grabPalette(paletteBackup, 0, 256);
+ for (int j = 0; j < 256; j++) {
+ blackPalette1[3 * j] = paletteBackup[3 * j] * fadeStep / 4;
+ blackPalette1[3 * j + 1] = paletteBackup[3 * j + 1] * fadeStep / 4;
+ blackPalette1[3 * j + 2] = paletteBackup[3 * j + 2] * fadeStep / 4;
+ }
+ fadeStep--;
+ _graph->setPalette(blackPalette1);
+ _system->updateScreen();
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ free(paletteBackup);
+ free(blackPalette1);
+ return;
+ }
+ pause();
+ }
+ free(paletteBackup);
+ free(blackPalette1);
+}
+
+void PrinceEngine::setPalette(const byte *palette) {
+ if (palette != nullptr) {
+ byte *blackPalette_ = (byte *)malloc(256 * 3);
+ int fadeStep = 0;
+ for (int i = 0; i <= kFadeStep; i++) {
+ for (int j = 0; j < 256; j++) {
+ blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
+ blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
+ blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
+ }
+ fadeStep++;
+ _graph->setPalette(blackPalette_);
+ _system->updateScreen();
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ _graph->setPalette(palette);
+ free(blackPalette_);
+ return;
+ }
+ pause();
+ }
+ _graph->setPalette(palette);
+ free(blackPalette_);
+ }
+}
+
+void PrinceEngine::pause() {
+ int delay = 1000 / kFPS - int32(_system->getMillis() - _currentTime);
+ delay = delay < 0 ? 0 : delay;
+ _system->delayMillis(delay);
+ _currentTime = _system->getMillis();
+}
+
+void PrinceEngine::pause2() {
+ int delay = 1000 / (kFPS * 2) - int32(_system->getMillis() - _currentTime);
+ delay = delay < 0 ? 0 : delay;
+ _system->delayMillis(delay);
+ _currentTime = _system->getMillis();
+}
+
+void PrinceEngine::addInv(int heroId, int item, bool addItemQuiet) {
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+ if (hero != nullptr) {
+ if (hero->_inventory.size() < kMaxItems) {
+ if (item != 0x7FFF) {
+ hero->_inventory.push_back(item);
+ }
+ if (!addItemQuiet) {
+ addInvObj();
+ }
+ _interpreter->setResult(0);
+ } else {
+ _interpreter->setResult(1);
+ }
+ }
+}
+
+void PrinceEngine::remInv(int heroId, int item) {
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+ if (hero != nullptr) {
+ for (uint i = 0; i < hero->_inventory.size(); i++) {
+ if (hero->_inventory[i] == item) {
+ hero->_inventory.remove_at(i);
+ _interpreter->setResult(0);
+ return;
+ }
+ }
+ }
+ _interpreter->setResult(1);
+}
+
+void PrinceEngine::clearInv(int heroId) {
+ switch (heroId) {
+ case 0:
+ _mainHero->_inventory.clear();
+ break;
+ case 1:
+ _secondHero->_inventory.clear();
+ break;
+ default:
+ error("clearInv() - wrong hero slot");
+ break;
+ }
+}
+
+void PrinceEngine::swapInv(int heroId) {
+ Common::Array<int> tempInv;
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+ if (hero != nullptr) {
+ for (uint i = 0; i < hero->_inventory.size(); i++) {
+ tempInv.push_back(hero->_inventory[i]);
+ }
+ hero->_inventory.clear();
+ for (uint i = 0; i < hero->_inventory2.size(); i++) {
+ hero->_inventory.push_back(hero->_inventory2[i]);
+ }
+ hero->_inventory2.clear();
+ for (uint i = 0; i < tempInv.size(); i++) {
+ hero->_inventory2.push_back(tempInv[i]);
+ }
+ tempInv.clear();
+ }
+}
+
+void PrinceEngine::addInvObj() {
+ changeCursor(0);
+ prepareInventoryToView();
+
+ _inventoryBackgroundRemember = true;
+ drawScreen();
+
+ Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
+
+ if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
+
+ loadSample(27, "PRZEDMIO.WAV");
+ playSample(27, 0);
+
+ _mst_shadow2 = 1;
+
+ while (_mst_shadow2 < 512) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 += 50;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pause();
+ }
+ while (_mst_shadow2 > 256) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 -= 42;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pause();
+ }
+ } else {
+ //CURSEBLINK:
+ for (int i = 0; i < 3; i++) {
+ _mst_shadow2 = 256;
+ while (_mst_shadow2 < 512) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 += 50;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pause();
+ }
+ while (_mst_shadow2 > 256) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 -= 50;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pause();
+ }
+ }
+ }
+ _mst_shadow2 = 0;
+ for (int i = 0; i < 20; i++) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pause();
+ }
+}
+
+void PrinceEngine::rememberScreenInv() {
+ _graph->_screenForInventory->copyFrom(*_graph->_frontScreen);
+}
+
+void PrinceEngine::inventoryFlagChange(bool inventoryState) {
+ if (inventoryState) {
+ _showInventoryFlag = true;
+ _inventoryBackgroundRemember = true;
+ } else {
+ _showInventoryFlag = false;
+ }
+}
+
+void PrinceEngine::prepareInventoryToView() {
+ _invMobList.clear();
+ int invItem = _mainHero->_inventory.size();
+ _invLine = invItem / 3;
+ if (invItem % 3) {
+ _invLine++;
+ }
+ if (_invLine < 4) {
+ _invLine = 4;
+ }
+ _maxInvW = (374 - 2 * _invLine) / _invLine;
+ _invLineW = _maxInvW - 2;
+
+ int currInvX = _invLineX;
+ int currInvY = _invLineY;
+
+ Common::MemoryReadStream stream(_invTxt, _invTxtSize);
+ byte c;
+
+ uint item = 0;
+ for (int i = 0; i < _invLines; i++) {
+ for (int j = 0; j < _invLine; j++) {
+ Mob tempMobItem;
+ if (item < _mainHero->_inventory.size()) {
+ int itemNr = _mainHero->_inventory[item];
+ tempMobItem._visible = 0;
+ tempMobItem._mask = itemNr;
+ tempMobItem._rect = Common::Rect(currInvX + _picWindowX, currInvY, currInvX + _picWindowX + _invLineW - 1, currInvY + _invLineH - 1);
+ tempMobItem._type = 0; // to work with checkMob()
+
+ tempMobItem._name = "";
+ tempMobItem._examText = "";
+ int txtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8]);
+ int examTxtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8 + 4]);
+
+ stream.seek(txtOffset);
+ while ((c = stream.readByte())) {
+ tempMobItem._name += c;
+ }
+
+ stream.seek(examTxtOffset);
+ while ((c = stream.readByte())) {
+ tempMobItem._examText += c;
+ }
+ _invMobList.push_back(tempMobItem);
+ }
+ currInvX += _invLineW + _invLineSkipX;
+ item++;
+ }
+ currInvX = _invLineX;
+ currInvY += _invLineSkipY + _invLineH;
+ }
+}
+
+void PrinceEngine::drawInvItems() {
+ int currInvX = _invLineX;
+ int currInvY = _invLineY;
+ uint item = 0;
+ for (int i = 0; i < _invLines; i++) {
+ for (int j = 0; j < _invLine; j++) {
+ if (item < _mainHero->_inventory.size()) {
+ int itemNr = _mainHero->_inventory[item];
+ _mst_shadow = 0;
+ if (_mst_shadow2) {
+ if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
+ if (item + 1 == _mainHero->_inventory.size()) { // last item in inventory
+ _mst_shadow = 1;
+ }
+ } else if (itemNr == 1 || itemNr == 3 || itemNr == 4 || itemNr == 7) {
+ _mst_shadow = 1;
+ }
+ }
+
+ int drawX = currInvX;
+ int drawY = currInvY;
+ Graphics::Surface *itemSurface = nullptr;
+ if (itemNr != 68) {
+ itemSurface = _allInvList[itemNr].getSurface();
+ if (itemSurface->h < _maxInvH) {
+ drawY += (_maxInvH - itemSurface->h) / 2;
+ }
+ } else {
+ // candle item:
+ if (_candleCounter == 8) {
+ _candleCounter = 0;
+ }
+ itemNr = _candleCounter;
+ _candleCounter++;
+ itemNr &= 7;
+ itemNr += 71;
+ itemSurface = _allInvList[itemNr].getSurface();
+ drawY += _allInvList[itemNr]._y + (_maxInvH - 76) / 2 - 200;
+ }
+ if (itemSurface->w < _maxInvW) {
+ drawX += (_maxInvW - itemSurface->w) / 2;
+ }
+ if (!_mst_shadow) {
+ _graph->drawTransparentSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
+ } else {
+ _mst_shadow = _mst_shadow2;
+ _graph->drawTransparentWithBlendSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
+ }
+ }
+ currInvX += _invLineW + _invLineSkipX;
+ item++;
+ }
+ currInvX = _invLineX;
+ currInvY += _invLineSkipY + _invLineH;
+ }
+}
+
+void PrinceEngine::walkTo() {
+ if (_mainHero->_visible) {
+ _mainHero->freeHeroAnim();
+ _mainHero->freeOldMove();
+ _interpreter->storeNewPC(_script->_scriptInfo.usdCode);
+ int destX, destY;
+ if (_optionsMob != -1) {
+ destX = _mobList[_optionsMob]._examPosition.x;
+ destY = _mobList[_optionsMob]._examPosition.y;
+ _mainHero->_destDirection = _mobList[_optionsMob]._examDirection;
+ } else {
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ destX = mousePos.x + _picWindowX;
+ destY = mousePos.y + _picWindowY;
+ _mainHero->_destDirection = 0;
+ }
+ _mainHero->_coords = makePath(kMainHero, _mainHero->_middleX, _mainHero->_middleY, destX, destY);
+ if (_mainHero->_coords != nullptr) {
+ _mainHero->_currCoords = _mainHero->_coords;
+ _mainHero->_dirTab = _directionTable;
+ _mainHero->_currDirTab = _directionTable;
+ _directionTable = nullptr;
+ _mainHero->_state = Hero::kHeroStateMove;
+ moveShandria();
+ }
+ }
+}
+
+void PrinceEngine::moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag) {
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+
+ if (hero != nullptr) {
+ if (dir) {
+ hero->_destDirection = dir;
+ }
+ if (x || y) {
+ hero->freeOldMove();
+ hero->_coords = makePath(heroId, hero->_middleX, hero->_middleY, x, y);
+ if (hero->_coords != nullptr) {
+ hero->_currCoords = hero->_coords;
+ hero->_dirTab = _directionTable;
+ hero->_currDirTab = _directionTable;
+ _directionTable = nullptr;
+ if (runHeroFlag) {
+ hero->_state = Hero::kHeroStateRun;
+ } else {
+ hero->_state = Hero::kHeroStateMove;
+ }
+ if (heroId == kMainHero && _mouseFlag) {
+ moveShandria();
+ }
+ }
+ } else {
+ hero->freeOldMove();
+ hero->_state = Hero::kHeroStateTurn;
+ }
+ hero->freeHeroAnim();
+ hero->_visible = 1;
+ }
+}
+
+void PrinceEngine::leftMouseButton() {
+ _flags->setFlagValue(Flags::LMOUSE, 1);
+ if (_flags->getFlagValue(Flags::POWERENABLED)) {
+ _flags->setFlagValue(Flags::MBFLAG, 1);
+ }
+ if (_mouseFlag) {
+ int option = 0;
+ int optionEvent = -1;
+
+ if (_optionsFlag) {
+ if (_optionEnabled < _optionsNumber && _optionEnabled != -1) {
+ option = _optionEnabled;
+ _optionsFlag = 0;
+ } else {
+ return;
+ }
+ } else {
+ _optionsMob = _selectedMob;
+ if (_optionsMob == -1) {
+ walkTo();
+ return;
+ }
+ option = 0;
+ }
+ //do_option
+ if (_currentPointerNumber != 2) {
+ //skip_use_code
+ int optionScriptOffset = _room->getOptionOffset(option);
+ if (optionScriptOffset != 0) {
+ optionEvent = _script->scanMobEvents(_optionsMob, optionScriptOffset);
+ }
+ if (optionEvent == -1) {
+ if (!option) {
+ walkTo();
+ return;
+ } else {
+ optionEvent = _script->getOptionStandardOffset(option);
+ }
+ }
+ } else if (_selectedMode) {
+ //give_item
+ if (_room->_itemGive) {
+ optionEvent = _script->scanMobEventsWithItem(_optionsMob, _room->_itemGive, _selectedItem);
+ }
+ if (optionEvent == -1) {
+ //standard_giveitem
+ optionEvent = _script->_scriptInfo.stdGiveItem;
+ }
+ } else {
+ if (_room->_itemUse) {
+ optionEvent = _script->scanMobEventsWithItem(_optionsMob, _room->_itemUse, _selectedItem);
+ _flags->setFlagValue(Flags::SELITEM, _selectedItem);
+ }
+ if (optionEvent == -1) {
+ //standard_useitem
+ optionEvent = _script->_scriptInfo.stdUseItem;
+ }
+ }
+ _interpreter->storeNewPC(optionEvent);
+ _flags->setFlagValue(Flags::CURRMOB, _selectedMob);
+ _selectedMob = -1;
+ _optionsMob = -1;
+ } else {
+ if (!_flags->getFlagValue(Flags::POWERENABLED)) {
+ if (!_flags->getFlagValue(Flags::NOCLSTEXT)) {
+ for (int slot = 0; slot < kMaxTexts; slot++) {
+ if (slot != 9) {
+ Text& text = _textSlots[slot];
+ if (!text._str) {
+ continue;
+ }
+ text._str = 0;
+ text._time = 0;
+ }
+ }
+ _mainHero->_talkTime = 0;
+ _secondHero->_talkTime = 0;
+ }
+ }
+ }
+}
+
+void PrinceEngine::rightMouseButton() {
+ if (_flags->getFlagValue(Flags::POWERENABLED)) {
+ _flags->setFlagValue(Flags::MBFLAG, 2);
+ }
+ if (_mouseFlag && _mouseFlag != 3) {
+ _mainHero->freeOldMove();
+ _secondHero->freeOldMove();
+ _interpreter->storeNewPC(0);
+ if (_currentPointerNumber < 2) {
+ enableOptions(true);
+ } else {
+ _currentPointerNumber = 1;
+ changeCursor(1);
+ }
+ }
+}
+
+void PrinceEngine::inventoryLeftMouseButton() {
+ if (!_mouseFlag) {
+ _textSlots[0]._time = 0;
+ _textSlots[0]._str = nullptr;
+ stopSample(28);
+ }
+
+ if (_optionsFlag == 1) {
+ if (_selectedMob != -1) {
+ if (_optionEnabled < _invOptionsNumber) {
+ _optionsFlag = 0;
+ } else {
+ return;
+ }
+ } else {
+ error("PrinceEngine::inventoryLeftMouseButton() - optionsFlag = 1, selectedMob = 0");
+ if (_currentPointerNumber == 2) {
+ changeCursor(1);
+ _currentPointerNumber = 1;
+ _selectedMob = -1;
+ _optionsMob = -1;
+ return;
+ } else {
+ return;
+ }
+ }
+ } else {
+ if (_selectedMob != -1) {
+ if (_currentPointerNumber != 2) {
+ if (_invMobList[_selectedMob]._mask != 29) {
+ _optionEnabled = 0;
+ } else {
+ // map item
+ _optionEnabled = 1;
+ }
+ } else {
+ //use_item_on_item
+ int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
+ if (invObjUU == -1) {
+ int textNr = 80011; // "I can't do it."
+ if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
+ textNr = 80020; // "Nothing is happening."
+ }
+ _interpreter->setCurrentString(textNr);
+ printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
+ setVoice(0, 28, 1);
+ playSample(28, 0);
+ _selectedMob = -1;
+ _optionsMob = -1;
+ return;
+ } else {
+ _interpreter->storeNewPC(invObjUU);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ }
+ } else {
+ return;
+ }
+ }
+ //do_option
+ if (_optionEnabled == 0) {
+ int invObjExamEvent = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjExam);
+ if (invObjExamEvent == -1) {
+ // do_standard
+ printAt(0, 216, (char *)_invMobList[_selectedMob]._examText.c_str(), kNormalWidth / 2, _invExamY);
+ _interpreter->setCurrentString(_invMobList[_selectedMob]._mask + 70000);
+ setVoice(0, 28, 1);
+ playSample(28, 0);
+ // disableuseuse
+ changeCursor(0);
+ _currentPointerNumber = 1;
+ } else {
+ _interpreter->storeNewPC(invObjExamEvent);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ } else if (_optionEnabled == 1) {
+ // not_examine
+ int invObjUse = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUse);
+ if (invObjUse == -1) {
+ // do_standard_use
+ _selectedMode = 0;
+ _selectedItem = _invMobList[_selectedMob]._mask;
+ makeInvCursor(_invMobList[_selectedMob]._mask);
+ _currentPointerNumber = 2;
+ changeCursor(2);
+ } else {
+ _interpreter->storeNewPC(invObjUse);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ } else if (_optionEnabled == 4) {
+ // do_standard_give
+ _selectedMode = 1;
+ _selectedItem = _invMobList[_selectedMob]._mask;
+ makeInvCursor(_invMobList[_selectedMob]._mask);
+ _currentPointerNumber = 2;
+ changeCursor(2);
+ } else {
+ // use_item_on_item
+ int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
+ if (invObjUU == -1) {
+ int textNr = 80011; // "I can't do it."
+ if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
+ textNr = 80020; // "Nothing is happening."
+ }
+ _interpreter->setCurrentString(textNr);
+ printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
+ setVoice(0, 28, 1);
+ playSample(28, 0);
+ } else {
+ _interpreter->storeNewPC(invObjUU);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ }
+ _selectedMob = -1;
+ _optionsMob = -1;
+}
+
+void PrinceEngine::inventoryRightMouseButton() {
+ if (_textSlots[0]._str == nullptr) {
+ enableOptions(false);
+ }
+}
+
+void PrinceEngine::enableOptions(bool checkType) {
+ if (_optionsFlag != 1) {
+ changeCursor(1);
+ _currentPointerNumber = 1;
+ if (_selectedMob != -1) {
+ if (checkType) {
+ if (_mobList[_selectedMob]._type & 0x100) {
+ return;
+ }
+ }
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ int x1 = mousePos.x - _optionsWidth / 2;
+ int x2 = mousePos.x + _optionsWidth / 2;
+ if (x1 < 0) {
+ x1 = 0;
+ x2 = _optionsWidth;
+ } else if (x2 >= kNormalWidth) {
+ x1 = kNormalWidth - _optionsWidth;
+ x2 = kNormalWidth;
+ }
+ int y1 = mousePos.y - 10;
+ if (y1 < 0) {
+ y1 = 0;
+ }
+ if (y1 + _optionsHeight >= kNormalHeight) {
+ y1 = kNormalHeight - _optionsHeight;
+ }
+ _optionsMob = _selectedMob;
+ _optionsX = x1;
+ _optionsY = y1;
+ _optionsFlag = 1;
+ }
+ }
+}
+
+void PrinceEngine::checkOptions() {
+ if (_optionsFlag) {
+ Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _optionsWidth, _optionsY + _optionsHeight);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ if (!optionsRect.contains(mousePos)) {
+ _optionsFlag = 0;
+ _selectedMob = -1;
+ return;
+ }
+ _graph->drawAsShadowSurface(_graph->_frontScreen, _optionsX, _optionsY, _optionsPic, _graph->_shadowTable50);
+
+ _optionEnabled = -1;
+ int optionsYCord = mousePos.y - (_optionsY + 16);
+ if (optionsYCord >= 0) {
+ int selectedOptionNr = optionsYCord / _optionsStep;
+ if (selectedOptionNr < _optionsNumber) {
+ _optionEnabled = selectedOptionNr;
+ }
+ }
+ int optionsColor;
+ int textY = _optionsY + 16;
+ for (int i = 0; i < _optionsNumber; i++) {
+ if (i != _optionEnabled) {
+ optionsColor = _optionsColor1;
+ } else {
+ optionsColor = _optionsColor2;
+ }
+ Common::String optText;
+ switch(getLanguage()) {
+ case Common::PL_POL:
+ optText = optionsTextPL[i];
+ break;
+ case Common::DE_DEU:
+ optText = optionsTextDE[i];
+ break;
+ case Common::EN_ANY:
+ optText = optionsTextEN[i];
+ break;
+ default:
+ break;
+ };
+ uint16 textW = getTextWidth(optText.c_str());
+ uint16 textX = _optionsX + _optionsWidth / 2 - textW / 2;
+ _font->drawString(_graph->_frontScreen, optText, textX, textY, textW, optionsColor);
+ textY += _optionsStep;
+ }
+ }
+}
+
+void PrinceEngine::checkInvOptions() {
+ if (_optionsFlag) {
+ Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _invOptionsWidth, _optionsY + _invOptionsHeight);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ if (!optionsRect.contains(mousePos)) {
+ _optionsFlag = 0;
+ _selectedMob = -1;
+ return;
+ }
+ _graph->drawAsShadowSurface(_graph->_screenForInventory, _optionsX, _optionsY, _optionsPicInInventory, _graph->_shadowTable50);
+
+ _optionEnabled = -1;
+ int optionsYCord = mousePos.y - (_optionsY + 16);
+ if (optionsYCord >= 0) {
+ int selectedOptionNr = optionsYCord / _invOptionsStep;
+ if (selectedOptionNr < _invOptionsNumber) {
+ _optionEnabled = selectedOptionNr;
+ }
+ }
+ int optionsColor;
+ int textY = _optionsY + 16;
+ for (int i = 0; i < _invOptionsNumber; i++) {
+ if (i != _optionEnabled) {
+ optionsColor = _optionsColor1;
+ } else {
+ optionsColor = _optionsColor2;
+ }
+ Common::String invText;
+ switch(getLanguage()) {
+ case Common::PL_POL:
+ invText = invOptionsTextPL[i];
+ break;
+ case Common::DE_DEU:
+ invText = invOptionsTextDE[i];
+ break;
+ case Common::EN_ANY:
+ invText = invOptionsTextEN[i];
+ break;
+ default:
+ error("Unknown game language %d", getLanguage());
+ break;
+ };
+ uint16 textW = getTextWidth(invText.c_str());
+ uint16 textX = _optionsX + _invOptionsWidth / 2 - textW / 2;
+ _font->drawString(_graph->_screenForInventory, invText, textX, textY, _graph->_screenForInventory->w, optionsColor);
+ textY += _invOptionsStep;
+ }
+ }
+}
+
+void PrinceEngine::displayInventory() {
+
+ _mainHero->freeOldMove();
+ _secondHero->freeOldMove();
+
+ _interpreter->setFgOpcodePC(0);
+
+ stopAllSamples();
+
+ prepareInventoryToView();
+
+ while (!shouldQuit()) {
+
+ if (_textSlots[0]._str != nullptr) {
+ changeCursor(0);
+ } else {
+ changeCursor(_currentPointerNumber);
+
+ Common::Rect inventoryRect(_invX1, _invY1, _invX1 + _invWidth, _invY1 + _invHeight);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+
+ if (!_invCurInside && inventoryRect.contains(mousePos)) {
+ _invCurInside = true;
+ }
+
+ if (_invCurInside && !inventoryRect.contains(mousePos)) {
+ inventoryFlagChange(false);
+ _invCurInside = false;
+ break;
+ }
+ }
+
+ rememberScreenInv();
+
+ Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+
+ drawInvItems();
+
+ showTexts(_graph->_screenForInventory);
+
+ if (!_optionsFlag && _textSlots[0]._str == nullptr) {
+ _selectedMob = checkMob(_graph->_screenForInventory, _invMobList, false);
+ }
+
+ checkInvOptions();
+
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ keyHandler(event);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ inventoryLeftMouseButton();
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ inventoryRightMouseButton();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!_showInventoryFlag) {
+ break;
+ }
+
+ if (shouldQuit())
+ return;
+
+ getDebugger()->onFrame();
+ _graph->update(_graph->_screenForInventory);
+ pause();
+ }
+
+ if (_currentPointerNumber == 2) {
+ _flags->setFlagValue(Flags::SELITEM, _selectedItem);
+ } else {
+ _flags->setFlagValue(Flags::SELITEM, 0);
+ }
+}
+
+void PrinceEngine::createDialogBox(int dialogBoxNr) {
+ _dialogLines = 0;
+ int amountOfDialogOptions = 0;
+ int dialogDataValue = (int)READ_LE_UINT32(_dialogData);
+
+ byte c;
+ int sentenceNumber;
+ _dialogText = _dialogBoxAddr[dialogBoxNr];
+ byte *dialogText = _dialogText;
+
+ while ((sentenceNumber = *dialogText) != 0xFF) {
+ dialogText++;
+ if (!(dialogDataValue & (1 << sentenceNumber))) {
+ _dialogLines += calcTextLines((const char *)dialogText);
+ amountOfDialogOptions++;
+ }
+ do {
+ c = *dialogText;
+ dialogText++;
+ } while (c);
+ }
+
+ _dialogHeight = _font->getFontHeight() * _dialogLines + _dialogLineSpace * (amountOfDialogOptions + 1);
+ _dialogImage = new Graphics::Surface();
+ _dialogImage->create(_dialogWidth, _dialogHeight, Graphics::PixelFormat::createFormatCLUT8());
+ Common::Rect dBoxRect(0, 0, _dialogWidth, _dialogHeight);
+ _dialogImage->fillRect(dBoxRect, _graph->kShadowColor);
+}
+
+void PrinceEngine::dialogRun() {
+
+ _dialogFlag = true;
+
+ while (!shouldQuit()) {
+
+ _interpreter->stepBg();
+ drawScreen();
+
+ int dialogX = (640 - _dialogWidth) / 2;
+ int dialogY = 460 - _dialogHeight;
+ _graph->drawAsShadowSurface(_graph->_frontScreen, dialogX, dialogY, _dialogImage, _graph->_shadowTable50);
+
+ int dialogSkipLeft = 14;
+ int dialogSkipUp = 10;
+
+ int dialogTextX = dialogX + dialogSkipLeft;
+ int dialogTextY = dialogY + dialogSkipUp;
+
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+
+ byte c;
+ int sentenceNumber;
+ byte *dialogText = _dialogText;
+ byte *dialogCurrentText = nullptr;
+ int dialogSelected = -1;
+ int dialogDataValue = (int)READ_LE_UINT32(_dialogData);
+
+ while ((sentenceNumber = *dialogText) != 0xFF) {
+ dialogText++;
+ int actualColor = _dialogColor1;
+
+ if (!(dialogDataValue & (1 << sentenceNumber))) {
+ if (getLanguage() == Common::DE_DEU) {
+ correctStringDEU((char *)dialogText);
+ }
+ Common::Array<Common::String> lines;
+ _font->wordWrapText((const char *)dialogText, _graph->_frontScreen->w, lines);
+
+ Common::Rect dialogOption(dialogTextX, dialogTextY - dialogSkipUp / 2, dialogX + _dialogWidth - dialogSkipLeft, dialogTextY + lines.size() * _font->getFontHeight() + dialogSkipUp / 2 - 1);
+ if (dialogOption.contains(mousePos)) {
+ actualColor = _dialogColor2;
+ dialogSelected = sentenceNumber;
+ dialogCurrentText = dialogText;
+ }
+
+ for (uint j = 0; j < lines.size(); j++) {
+ _font->drawString(_graph->_frontScreen, lines[j], dialogTextX, dialogTextY, _graph->_frontScreen->w, actualColor);
+ dialogTextY += _font->getFontHeight();
+ }
+ dialogTextY += _dialogLineSpace;
+ }
+ do {
+ c = *dialogText;
+ dialogText++;
+ } while (c);
+ }
+
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ keyHandler(event);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ if (dialogSelected != -1) {
+ dialogLeftMouseButton(dialogCurrentText, dialogSelected);
+ _dialogFlag = false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (shouldQuit()) {
+ return;
+ }
+
+ if (!_dialogFlag) {
+ break;
+ }
+
+ getDebugger()->onFrame();
+ _graph->update(_graph->_frontScreen);
+ pause();
+ }
+ _dialogImage->free();
+ delete _dialogImage;
+ _dialogImage = nullptr;
+ _dialogFlag = false;
+}
+
+void PrinceEngine::dialogLeftMouseButton(byte *string, int dialogSelected) {
+ _interpreter->setString(string);
+ talkHero(0);
+
+ int dialogDataValue = (int)READ_LE_UINT32(_dialogData);
+ dialogDataValue |= (1u << dialogSelected);
+ WRITE_LE_UINT32(_dialogData, dialogDataValue);
+
+ _flags->setFlagValue(Flags::BOXSEL, dialogSelected + 1);
+ setVoice(0, 28, dialogSelected + 1);
+
+ _flags->setFlagValue(Flags::VOICE_H_LINE, _dialogOptLines[dialogSelected * 4]);
+ _flags->setFlagValue(Flags::VOICE_A_LINE, _dialogOptLines[dialogSelected * 4 + 1]);
+ _flags->setFlagValue(Flags::VOICE_B_LINE, _dialogOptLines[dialogSelected * 4 + 2]);
+
+ _interpreter->setString(_dialogOptAddr[dialogSelected]);
+}
+
+void PrinceEngine::talkHero(int slot) {
+ // heroSlot = textSlot (slot 0 or 1)
+ Text &text = _textSlots[slot];
+ int lines = calcTextLines((const char *)_interpreter->getString());
+ int time = lines * 30;
+
+ if (slot == 0) {
+ text._color = 220; // TODO - test this
+ _mainHero->_state = Hero::kHeroStateTalk;
+ _mainHero->_talkTime = time;
+ text._x = _mainHero->_middleX;
+ text._y = _mainHero->_middleY - _mainHero->_scaledFrameYSize;
+ } else {
+ text._color = _flags->getFlagValue(Flags::KOLOR); // TODO - test this
+ _secondHero->_state = Hero::kHeroStateTalk;
+ _secondHero->_talkTime = time;
+ text._x = _secondHero->_middleX;
+ text._y = _secondHero->_middleY - _secondHero->_scaledFrameYSize;
+ }
+ text._time = time;
+ if (getLanguage() == Common::DE_DEU) {
+ correctStringDEU((char *)_interpreter->getString());
+ }
+ text._str = (const char *)_interpreter->getString();
+ _interpreter->increaseString();
+}
+
+void PrinceEngine::doTalkAnim(int animNumber, int slot, AnimType animType) {
+ Text &text = _textSlots[slot];
+ int lines = calcTextLines((const char *)_interpreter->getString());
+ int time = lines * 30;
+ if (animType == kNormalAnimation) {
+ Anim &normAnim = _normAnimList[animNumber];
+ if (normAnim._animData != nullptr) {
+ if (!normAnim._state) {
+ if (normAnim._currW && normAnim._currH) {
+ text._color = _flags->getFlagValue(Flags::KOLOR);
+ text._x = normAnim._currX + normAnim._currW / 2;
+ text._y = normAnim._currY - 10;
+ }
+ }
+ }
+ } else if (animType == kBackgroundAnimation) {
+ if (!_backAnimList[animNumber].backAnims.empty()) {
+ int currAnim = _backAnimList[animNumber]._seq._currRelative;
+ Anim &backAnim = _backAnimList[animNumber].backAnims[currAnim];
+ if (backAnim._animData != nullptr) {
+ if (!backAnim._state) {
+ if (backAnim._currW && backAnim._currH) {
+ text._color = _flags->getFlagValue(Flags::KOLOR);
+ text._x = backAnim._currX + backAnim._currW / 2;
+ text._y = backAnim._currY - 10;
+ }
+ }
+ }
+ }
+ } else {
+ error("doTalkAnim() - wrong animType: %d", animType);
+ }
+ text._time = time;
+ if (getLanguage() == Common::DE_DEU) {
+ correctStringDEU((char *)_interpreter->getString());
+ }
+ text._str = (const char *)_interpreter->getString();
+ _interpreter->increaseString();
+}
+
+void PrinceEngine::freeNormAnim(int slot) {
+ if (!_normAnimList.empty()) {
+ _normAnimList[slot]._state = 1;
+ if (_normAnimList[slot]._animData != nullptr) {
+ delete _normAnimList[slot]._animData;
+ _normAnimList[slot]._animData = nullptr;
+ }
+ if (_normAnimList[slot]._shadowData != nullptr) {
+ delete _normAnimList[slot]._shadowData;
+ _normAnimList[slot]._shadowData = nullptr;
+ }
+ }
+}
+
+void PrinceEngine::freeAllNormAnims() {
+ for (int i = 0; i < kMaxNormAnims; i++) {
+ freeNormAnim(i);
+ }
+}
+
+void PrinceEngine::getCurve() {
+ _flags->setFlagValue(Flags::TORX1, _curveData[_curvPos]);
+ _flags->setFlagValue(Flags::TORY1, _curveData[_curvPos + 1]);
+ _curvPos += 2;
+}
+
+void PrinceEngine::makeCurve() {
+ _curvPos = 0;
+ int x1 = _flags->getFlagValue(Flags::TORX1);
+ int y1 = _flags->getFlagValue(Flags::TORY1);
+ int x2 = _flags->getFlagValue(Flags::TORX2);
+ int y2 = _flags->getFlagValue(Flags::TORY2);
+
+ for (int i = 0; i < kCurveLen; i++) {
+ int sum1 = x1 * curveValues[i][0];
+ sum1 += (x2 + (x1 - x2) / 2) * curveValues[i][1];
+ sum1 += x2 * curveValues[i][2];
+ sum1 += x2 * curveValues[i][3];
+
+ int sum2 = y1 * curveValues[i][0];
+ sum2 += (y2 - 20) * curveValues[i][1];
+ sum2 += (y2 - 10) * curveValues[i][2];
+ sum2 += y2 * curveValues[i][3];
+
+ _curveData[i * 2] = (sum1 >> 15);
+ _curveData[i * 2 + 1] = (sum2 >> 15);
+ }
+}
+
+void PrinceEngine::mouseWeirdo() {
+ if (_mouseFlag == 3) {
+ int weirdDir = _randomSource.getRandomNumber(3);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ switch (weirdDir) {
+ case 0:
+ mousePos.x += kCelStep;
+ break;
+ case 1:
+ mousePos.x -= kCelStep;
+ break;
+ case 2:
+ mousePos.y += kCelStep;
+ break;
+ case 3:
+ mousePos.y -= kCelStep;
+ break;
+ }
+ mousePos.x = CLIP(mousePos.x, (int16) 315, (int16) 639);
+ _flags->setFlagValue(Flags::MXFLAG, mousePos.x);
+ mousePos.y = CLIP(mousePos.y, (int16) 0, (int16) 170);
+ _flags->setFlagValue(Flags::MYFLAG, mousePos.y);
+ _system->warpMouse(mousePos.x, mousePos.y);
+ }
+}
+
+void PrinceEngine::showPower() {
+ if (_flags->getFlagValue(Flags::POWERENABLED)) {
+ int power = _flags->getFlagValue(Flags::POWER);
+
+ byte *dst = (byte *)_graph->_frontScreen->getBasePtr(kPowerBarPosX, kPowerBarPosY);
+ for (int y = 0; y < kPowerBarHeight; y++) {
+ byte *dst2 = dst;
+ for (int x = 0; x < kPowerBarWidth; x++, dst2++) {
+ *dst2 = kPowerBarBackgroundColor;
+ }
+ dst += _graph->_frontScreen->pitch;
+ }
+
+ if (power) {
+ dst = (byte *)_graph->_frontScreen->getBasePtr(kPowerBarPosX, kPowerBarGreenPosY);
+ for (int y = 0; y < kPowerBarGreenHeight; y++) {
+ byte *dst2 = dst;
+ for (int x = 0; x < power + 1; x++, dst2++) {
+ if (x < 58) {
+ *dst2 = kPowerBarGreenColor1;
+ } else {
+ *dst2 = kPowerBarGreenColor2;
+ }
+ }
+ dst += _graph->_frontScreen->pitch;
+ }
+ }
+
+ _graph->change();
+ }
+}
+
+void PrinceEngine::scrollCredits() {
+ byte *scrollAdress = _creditsData;
+ while (!shouldQuit()) {
+ for (int scrollPos = 0; scrollPos > -23; scrollPos--) {
+ const Graphics::Surface *roomSurface = _roomBmp->getSurface();
+ if (roomSurface) {
+ _graph->draw(_graph->_frontScreen, roomSurface);
+ }
+ char *s = (char *)scrollAdress;
+ int drawY = scrollPos;
+ for (int i = 0; i < 22; i++) {
+ Common::String line;
+ char *linePos = s;
+ while ((*linePos != 13)) {
+ line += *linePos;
+ linePos++;
+ }
+ if (!line.empty()) {
+ int drawX = (kNormalWidth - getTextWidth(line.c_str())) / 2;
+ _font->drawString(_graph->_frontScreen, line, drawX, drawY, _graph->_frontScreen->w, 217);
+ }
+
+ char letter1;
+ bool gotIt1 = false;
+ do {
+ letter1 = *s;
+ s++;
+ if (letter1 == 13) {
+ if (*s == 10) {
+ s++;
+ }
+ if (*s != 35) {
+ gotIt1 = true;
+ }
+ break;
+ }
+ } while (letter1 != 35);
+
+ if (gotIt1) {
+ drawY += 23;
+ } else {
+ break;
+ }
+ }
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ if (event.type == Common::EVENT_KEYDOWN) {
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ blackPalette();
+ return;
+ }
+ }
+ }
+ if (shouldQuit()) {
+ return;
+ }
+ _graph->change();
+ _graph->update(_graph->_frontScreen);
+ pause2();
+ }
+ char letter2;
+ byte *scan2 = scrollAdress;
+ bool gotIt2 = false;
+ do {
+ letter2 = *scan2;
+ scan2++;
+ if (letter2 == 13) {
+ if (*scan2 == 10) {
+ scan2++;
+ }
+ if (*scan2 != 35) {
+ gotIt2 = true;
+ }
+ break;
+ }
+ } while (letter2 != 35);
+ if (gotIt2) {
+ scrollAdress = scan2;
+ } else {
+ break;
+ }
+ }
+ blackPalette();
+}
+
+// Modified version of Graphics::drawLine() to allow breaking the loop and return value
+int PrinceEngine::drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data) {
+ // Bresenham's line algorithm, as described by Wikipedia
+ const bool steep = ABS(y1 - y0) > ABS(x1 - x0);
+
+ if (steep) {
+ SWAP(x0, y0);
+ SWAP(x1, y1);
+ }
+
+ const int delta_x = ABS(x1 - x0);
+ const int delta_y = ABS(y1 - y0);
+ const int delta_err = delta_y;
+ int x = x0;
+ int y = y0;
+ int err = 0;
+
+ const int x_step = (x0 < x1) ? 1 : -1;
+ const int y_step = (y0 < y1) ? 1 : -1;
+
+ int stopFlag = 0;
+ if (steep)
+ stopFlag = (*plotProc)(y, x, data);
+ else
+ stopFlag = (*plotProc)(x, y, data);
+
+ while (x != x1 && !stopFlag) {
+ x += x_step;
+ err += delta_err;
+ if (2 * err > delta_x) {
+ y += y_step;
+ err -= delta_x;
+ }
+ if (steep)
+ stopFlag = (*plotProc)(y, x, data);
+ else
+ stopFlag = (*plotProc)(x, y, data);
+ }
+ return stopFlag;
+}
+
+int PrinceEngine::getPixelAddr(byte *pathBitmap, int x, int y) {
+ int mask = 128 >> (x & 7);
+ byte value = pathBitmap[x / 8 + y * 80];
+ return (mask & value);
+}
+
+void PrinceEngine::findPoint(int x, int y) {
+ _fpX = x;
+ _fpY = y;
+
+ if (getPixelAddr(_roomPathBitmap, x, y)) {
+ return;
+ }
+
+ int fpL = x;
+ int fpU = y;
+ int fpR = x;
+ int fpD = y;
+
+ while (1) {
+ if (fpD != kMaxPicHeight) {
+ if (getPixelAddr(_roomPathBitmap, x, fpD)) {
+ _fpX = x;
+ _fpY = fpD;
+ break;
+ }
+ fpD++;
+ }
+ if (fpU) {
+ if (getPixelAddr(_roomPathBitmap, x, fpU)) {
+ _fpX = x;
+ _fpY = fpU;
+ break;
+ }
+ fpU--;
+ }
+ if (fpL) {
+ if (getPixelAddr(_roomPathBitmap, fpL, y)) {
+ _fpX = fpL;
+ _fpY = y;
+ break;
+ }
+ fpL--;
+ }
+ if (fpR != _sceneWidth) {
+ if (getPixelAddr(_roomPathBitmap, fpR, y)) {
+ _fpX = fpR;
+ _fpY = y;
+ break;
+ }
+ fpR++;
+ }
+ if (!fpU && (fpD == kMaxPicHeight)) {
+ if (!fpL && (fpR == _sceneWidth)) {
+ break;
+ }
+ }
+ }
+}
+
+Direction PrinceEngine::makeDirection(int x1, int y1, int x2, int y2) {
+ if (x1 != x2) {
+ if (y1 != y2) {
+ if (x1 > x2) {
+ if (y1 > y2) {
+ if (x1 - x2 >= y1 - y2) {
+ return kDirLU;
+ } else {
+ return kDirUL;
+ }
+ } else {
+ if (x1 - x2 >= y2 - y1) {
+ return kDirLD;
+ } else {
+ return kDirDL;
+ }
+ }
+ } else {
+ if (y1 > y2) {
+ if (x2 - x1 >= y1 - y2) {
+ return kDirRU;
+ } else {
+ return kDirUR;
+ }
+ } else {
+ if (x2 - x1 >= y2 - y1) {
+ return kDirRD;
+ } else {
+ return kDirDR;
+ }
+ }
+ }
+ } else {
+ if (x1 >= x2) {
+ return kDirL;
+ } else {
+ return kDirR;
+ }
+ }
+ } else {
+ if (y1 >= y2) {
+ return kDirU;
+ } else {
+ return kDirD;
+ }
+ }
+}
+
+void PrinceEngine::specialPlot(int x, int y) {
+ if (_coords < _coordsBufEnd) {
+ WRITE_LE_UINT16(_coords, x);
+ _coords += 2;
+ WRITE_LE_UINT16(_coords, y);
+ _coords += 2;
+ specialPlot2(x, y);
+ }
+}
+
+void PrinceEngine::specialPlot2(int x, int y) {
+ int mask = 128 >> (x & 7);
+ _roomPathBitmapTemp[x / 8 + y * 80] |= mask;
+}
+
+void PrinceEngine::specialPlotInside(int x, int y) {
+ if (_coords < _coordsBufEnd) {
+ WRITE_LE_UINT16(_coords, x);
+ _coords += 2;
+ WRITE_LE_UINT16(_coords, y);
+ _coords += 2;
+ }
+}
+
+int PrinceEngine::plotTraceLine(int x, int y, void *data) {
+ PrinceEngine *traceLine = (PrinceEngine *)data;
+ if (!traceLine->_traceLineFirstPointFlag) {
+ if (!traceLine->getPixelAddr(traceLine->_roomPathBitmapTemp, x, y)) {
+ if (traceLine->getPixelAddr(traceLine->_roomPathBitmap, x, y)) {
+ traceLine->specialPlotInside(x, y);
+ traceLine->_traceLineLen++;
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ return 1;
+ }
+ } else {
+ traceLine->_traceLineFirstPointFlag = false;
+ return 0;
+ }
+}
+
+int PrinceEngine::leftDownDir() {
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::leftDir() {
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::leftUpDir() {
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::rightDownDir() {
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::rightDir() {
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::rightUpDir() {
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::upLeftDir() {
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::upDir() {
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::upRightDir() {
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::downLeftDir() {
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::downDir() {
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::downRightDir() {
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::cpe() {
+ if ((*(_checkBitmap - kPBW) & _checkMask)) {
+ if ((*(_checkBitmap + kPBW) & _checkMask)) {
+ int value;
+ switch (_checkMask) {
+ case 128:
+ value = READ_LE_UINT16(_checkBitmap - 1);
+ value &= 0x4001;
+ if (value != 0x4001) {
+ return 0;
+ }
+ break;
+ case 64:
+ value = *_checkBitmap;
+ value &= 0xA0;
+ if (value != 0xA0) {
+ return 0;
+ }
+ break;
+ case 32:
+ value = *_checkBitmap;
+ value &= 0x50;
+ if (value != 0x50) {
+ return 0;
+ }
+ break;
+ case 16:
+ value = *_checkBitmap;
+ value &= 0x28;
+ if (value != 0x28) {
+ return 0;
+ }
+ break;
+ case 8:
+ value = *_checkBitmap;
+ value &= 0x14;
+ if (value != 0x14) {
+ return 0;
+ }
+ break;
+ case 4:
+ value = *_checkBitmap;
+ value &= 0xA;
+ if (value != 0xA) {
+ return 0;
+ }
+ break;
+ case 2:
+ value = *_checkBitmap;
+ value &= 0x5;
+ if (value != 0x5) {
+ return 0;
+ }
+ break;
+ case 1:
+ value = READ_LE_UINT16(_checkBitmap);
+ value &= 0x8002;
+ if (value != 0x8002) {
+ return 0;
+ }
+ break;
+ default:
+ error("Wrong _checkMask value - cpe()");
+ break;
+ }
+ _checkX = _rembX;
+ _checkY = _rembY;
+ _checkBitmapTemp = _rembBitmapTemp;
+ _checkBitmap = _rembBitmap;
+ _checkMask = _rembMask;
+ return -1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int PrinceEngine::checkLeftDownDir() {
+ if (_checkX && _checkY != (kMaxPicHeight / 2 - 1)) {
+ int tempMask = _checkMask;
+ if (tempMask != 128) {
+ tempMask <<= 1;
+ if ((*(_checkBitmap + kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
+ _checkBitmap += kPBW;
+ _checkBitmapTemp += kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap + kPBW - 1) & 1)) {
+ if (!(*(_checkBitmapTemp + kPBW - 1) & 1)) {
+ _checkBitmap += (kPBW - 1);
+ _checkBitmapTemp += (kPBW - 1);
+ _checkMask = 1;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX--;
+ _checkY++;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkLeftDir() {
+ if (_checkX) {
+ int tempMask = _checkMask;
+ if (tempMask != 128) {
+ tempMask <<= 1;
+ if ((*(_checkBitmap) & tempMask)) {
+ if (!(*(_checkBitmapTemp) & tempMask)) {
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap - 1) & 1)) {
+ if (!(*(_checkBitmapTemp - 1) & 1)) {
+ _checkBitmap--;
+ _checkBitmapTemp--;
+ _checkMask = 1;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX--;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkDownDir() {
+ if (_checkY != (kMaxPicHeight / 2 - 1)) {
+ if ((*(_checkBitmap + kPBW) & _checkMask)) {
+ if (!(*(_checkBitmapTemp + kPBW) & _checkMask)) {
+ _checkBitmap += kPBW;
+ _checkBitmapTemp += kPBW;
+ _checkY++;
+ return cpe();
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkUpDir() {
+ if (_checkY) {
+ if ((*(_checkBitmap - kPBW) & _checkMask)) {
+ if (!(*(_checkBitmapTemp - kPBW) & _checkMask)) {
+ _checkBitmap -= kPBW;
+ _checkBitmapTemp -= kPBW;
+ _checkY--;
+ return cpe();
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkRightDir() {
+ if (_checkX != (kMaxPicWidth / 2 - 1)) {
+ int tempMask = _checkMask;
+ if (tempMask != 1) {
+ tempMask >>= 1;
+ if ((*(_checkBitmap) & tempMask)) {
+ if (!(*(_checkBitmapTemp) & tempMask)) {
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap + 1) & 128)) {
+ if (!(*(_checkBitmapTemp + 1) & 128)) {
+ _checkBitmap++;
+ _checkBitmapTemp++;
+ _checkMask = 128;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX++;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkLeftUpDir() {
+ if (_checkX && _checkY) {
+ int tempMask = _checkMask;
+ if (tempMask != 128) {
+ tempMask <<= 1;
+ if ((*(_checkBitmap - kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
+ _checkBitmap -= kPBW;
+ _checkBitmapTemp -= kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap - (kPBW + 1)) & 1)) {
+ if (!(*(_checkBitmapTemp - (kPBW + 1)) & 1)) {
+ _checkBitmap -= (kPBW + 1);
+ _checkBitmapTemp -= (kPBW + 1);
+ _checkMask = 1;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX--;
+ _checkY--;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkRightDownDir() {
+ if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY != (kMaxPicHeight / 2 - 1)) {
+ int tempMask = _checkMask;
+ if (tempMask != 1) {
+ tempMask >>= 1;
+ if ((*(_checkBitmap + kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
+ _checkBitmap += kPBW;
+ _checkBitmapTemp += kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap + kPBW + 1) & 128)) {
+ if (!(*(_checkBitmapTemp + kPBW + 1) & 128)) {
+ _checkBitmap += kPBW + 1;
+ _checkBitmapTemp += kPBW + 1;
+ _checkMask = 128;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX++;
+ _checkY++;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkRightUpDir() {
+ if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY) {
+ int tempMask = _checkMask;
+ if (tempMask != 1) {
+ tempMask >>= 1;
+ if ((*(_checkBitmap - kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
+ _checkBitmap -= kPBW;
+ _checkBitmapTemp -= kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap - kPBW + 1) & 128)) {
+ if (!(*(_checkBitmapTemp - kPBW + 1) & 128)) {
+ _checkBitmap -= (kPBW - 1);
+ _checkBitmapTemp -= (kPBW - 1);
+ _checkMask = 128;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX++;
+ _checkY--;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+bool PrinceEngine::tracePath(int x1, int y1, int x2, int y2) {
+ for (int i = 0; i < kPathBitmapLen; i++) {
+ _roomPathBitmapTemp[i] = 0;
+ }
+ if (x1 != x2 || y1 != y2) {
+ if (getPixelAddr(_roomPathBitmap, x1, y1)) {
+ if (getPixelAddr(_roomPathBitmap, x2, y2)) {
+ _coords = _coordsBuf;
+ specialPlot(x1, y1);
+
+ int x = x1;
+ int y = y1;
+
+ while (1) {
+ int btx = x;
+ int bty = y;
+ byte *bcad = _coords;
+
+ _traceLineLen = 0;
+ _traceLineFirstPointFlag = true;
+ int drawLineFlag = drawLine(x, y, x2, y2, &this->plotTraceLine, this);
+
+ if (!drawLineFlag) {
+ return true;
+ } else if (drawLineFlag == -1 && _traceLineLen >= 2) {
+ byte *tempCorrds = bcad;
+ while (tempCorrds != _coords) {
+ x = READ_LE_UINT16(tempCorrds);
+ y = READ_LE_UINT16(tempCorrds + 2);
+ tempCorrds += 4;
+ specialPlot2(x, y);
+ }
+ } else {
+ _coords = bcad;
+ x = btx;
+ y = bty;
+ }
+
+ Direction dir = makeDirection(x, y, x2, y2);
+
+ _rembBitmapTemp = &_roomPathBitmapTemp[x / 8 + y * 80];
+ _rembBitmap = &_roomPathBitmap[x / 8 + y * 80];
+ _rembMask = 128 >> (x & 7);
+ _rembX = x;
+ _rembY = y;
+
+ _checkBitmapTemp = _rembBitmapTemp;
+ _checkBitmap = _rembBitmap;
+ _checkMask = _rembMask;
+ _checkX = _rembX;
+ _checkY = _rembY;
+
+ int result;
+ switch (dir) {
+ case kDirLD:
+ result = leftDownDir();
+ break;
+ case kDirL:
+ result = leftDir();
+ break;
+ case kDirLU:
+ result = leftUpDir();
+ break;
+ case kDirRD:
+ result = rightDownDir();
+ break;
+ case kDirR:
+ result = rightDir();
+ break;
+ case kDirRU:
+ result = rightUpDir();
+ break;
+ case kDirUL:
+ result = upLeftDir();
+ break;
+ case kDirU:
+ result = upDir();
+ break;
+ case kDirUR:
+ result = upRightDir();
+ break;
+ case kDirDL:
+ result = downLeftDir();
+ break;
+ case kDirD:
+ result = downDir();
+ break;
+ case kDirDR:
+ result = downRightDir();
+ break;
+ default:
+ result = -1;
+ error("tracePath: wrong direction %d", dir);
+ break;
+ }
+
+ if (result) {
+ byte *tempCoords = _coords;
+ tempCoords -= 4;
+ if (tempCoords > _coordsBuf) {
+ int tempX = READ_LE_UINT16(tempCoords);
+ int tempY = READ_LE_UINT16(tempCoords + 2);
+ if (_checkX == tempX && _checkY == tempY) {
+ _coords = tempCoords;
+ }
+ x = READ_LE_UINT16(tempCoords);
+ y = READ_LE_UINT16(tempCoords + 2);
+ } else {
+ return false;
+ }
+ } else {
+ x = _checkX;
+ y = _checkY;
+ }
+ }
+ return true;
+ } else {
+ error("tracePath: wrong destination point");
+ }
+ } else {
+ error("tracePath: wrong start point");
+ }
+ } else {
+ error("tracePath: same point");
+ }
+}
+
+void PrinceEngine::specialPlotInside2(int x, int y) {
+ WRITE_LE_UINT16(_coords2, x);
+ _coords2 += 2;
+ WRITE_LE_UINT16(_coords2, y);
+ _coords2 += 2;
+}
+
+int PrinceEngine::plotTracePoint(int x, int y, void *data) {
+ PrinceEngine *tracePoint = (PrinceEngine *)data;
+ if (!tracePoint->_tracePointFirstPointFlag) {
+ if (tracePoint->getPixelAddr(tracePoint->_roomPathBitmap, x, y)) {
+ tracePoint->specialPlotInside2(x, y);
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ tracePoint->_tracePointFirstPointFlag = false;
+ return 0;
+ }
+}
+
+void PrinceEngine::approxPath() {
+ byte *oldCoords;
+ _coords2 = _coordsBuf2;
+ byte *tempCoordsBuf = _coordsBuf; // first point on path
+ byte *tempCoords = _coords;
+ if (tempCoordsBuf != tempCoords) {
+ tempCoords -= 4; // last point on path
+ while (tempCoordsBuf != tempCoords) {
+ int x1 = READ_LE_UINT16(tempCoords);
+ int y1 = READ_LE_UINT16(tempCoords + 2);
+ int x2 = READ_LE_UINT16(tempCoordsBuf);
+ int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
+ tempCoordsBuf += 4;
+ //TracePoint
+ oldCoords = _coords2;
+ if (_coords2 == _coordsBuf2) {
+ WRITE_LE_UINT16(_coords2, x1);
+ WRITE_LE_UINT16(_coords2 + 2, y1);
+ _coords2 += 4;
+ } else {
+ int testX = READ_LE_UINT16(_coords2 - 4);
+ int testY = READ_LE_UINT16(_coords2 - 2);
+ if (testX != x1 || testY != y1) {
+ WRITE_LE_UINT16(_coords2, x1);
+ WRITE_LE_UINT16(_coords2 + 2, y1);
+ _coords2 += 4;
+ }
+ }
+ _tracePointFirstPointFlag = true;
+ bool drawLineFlag = drawLine(x1, y1, x2, y2, &this->plotTracePoint, this);
+ if (!drawLineFlag) {
+ tempCoords = tempCoordsBuf - 4;
+ tempCoordsBuf = _coordsBuf;
+ } else {
+ _coords2 = oldCoords;
+ }
+ }
+ }
+}
+
+void PrinceEngine::freeDirectionTable() {
+ if (_directionTable != nullptr) {
+ free(_directionTable);
+ _directionTable = nullptr;
+ }
+}
+
+int PrinceEngine::scanDirectionsFindNext(byte *tempCoordsBuf, int xDiff, int yDiff) {
+
+ int tempX, tempY, direction;
+
+ tempX = Hero::kHeroDirLeft;
+ if (xDiff < 0) {
+ tempX = Hero::kHeroDirRight;
+ }
+
+ tempY = Hero::kHeroDirUp;
+ if (yDiff < 0) {
+ tempY = Hero::kHeroDirDown;
+ }
+
+ while (1) {
+ int againPointX1 = READ_LE_UINT16(tempCoordsBuf);
+ int againPointY1 = READ_LE_UINT16(tempCoordsBuf + 2);
+ tempCoordsBuf += 4;
+
+ if (tempCoordsBuf == _coords) {
+ direction = tempX;
+ break;
+ }
+
+ int dX = againPointX1 - READ_LE_UINT16(tempCoordsBuf);
+ int dY = againPointY1 - READ_LE_UINT16(tempCoordsBuf + 2);
+
+ if (dX != xDiff) {
+ direction = tempY;
+ break;
+ }
+
+ if (dY != yDiff) {
+ direction = tempX;
+ break;
+ }
+ }
+ return direction;
+}
+
+void PrinceEngine::scanDirections() {
+ freeDirectionTable();
+ byte *tempCoordsBuf = _coordsBuf;
+ if (tempCoordsBuf != _coords) {
+ int size = (_coords - tempCoordsBuf) / 4 + 1; // number of coord points plus one for end marker
+ _directionTable = (byte *)malloc(size);
+ byte *tempDirTab = _directionTable;
+ int direction = -1;
+ int lastDirection = -1;
+
+ while (1) {
+ int x1 = READ_LE_UINT16(tempCoordsBuf);
+ int y1 = READ_LE_UINT16(tempCoordsBuf + 2);
+ tempCoordsBuf += 4;
+ if (tempCoordsBuf == _coords) {
+ break;
+ }
+ int x2 = READ_LE_UINT16(tempCoordsBuf);
+ int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
+
+ int xDiff = x1 - x2;
+ int yDiff = y1 - y2;
+
+ if (xDiff) {
+ if (yDiff) {
+ if (lastDirection != -1) {
+ direction = lastDirection;
+ if (direction == Hero::kHeroDirLeft) {
+ if (xDiff < 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else if (direction == Hero::kHeroDirRight) {
+ if (xDiff >= 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else if (direction == Hero::kHeroDirUp) {
+ if (yDiff < 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else {
+ if (yDiff >= 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ }
+ } else {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else {
+ direction = Hero::kHeroDirLeft;
+ if (xDiff < 0) {
+ direction = Hero::kHeroDirRight;
+ }
+ }
+ } else {
+ if (yDiff) {
+ direction = Hero::kHeroDirUp;
+ if (yDiff < 0) {
+ direction = Hero::kHeroDirDown;
+ }
+ } else {
+ direction = lastDirection;
+ }
+ }
+ lastDirection = direction;
+ *tempDirTab = direction;
+ tempDirTab++;
+ }
+ *tempDirTab = *(tempDirTab - 1);
+ tempDirTab++;
+ *tempDirTab = 0;
+ }
+}
+
+void PrinceEngine::moveShandria() {
+ int shanLen1 = _shanLen;
+ if (_flags->getFlagValue(Flags::SHANDOG)) {
+ _secondHero->freeHeroAnim();
+ _secondHero->freeOldMove();
+ byte *shanCoords = _mainHero->_currCoords + shanLen1 * 4 - 4;
+ int shanX = READ_LE_UINT16(shanCoords - 4);
+ int shanY = READ_LE_UINT16(shanCoords - 2);
+ int xDiff = shanX - _secondHero->_middleX;
+ if (xDiff < 0) {
+ xDiff *= -1;
+ }
+ int yDiff = shanY - _secondHero->_middleY;
+ if (yDiff < 0) {
+ yDiff *= -1;
+ }
+ shanCoords -= 4;
+ if (shanCoords != _mainHero->_currCoords) {
+ yDiff *= 1.5;
+ int shanDis = xDiff * xDiff + yDiff * yDiff;
+ if (shanDis >= kMinDistance) {
+ while (1) {
+ shanCoords -= 4;
+ if (shanCoords == _mainHero->_currCoords) {
+ break;
+ }
+ int x = READ_LE_UINT16(shanCoords);
+ int y = READ_LE_UINT16(shanCoords + 2);
+ int pointDiffX = x - shanX;
+ if (pointDiffX < 0) {
+ pointDiffX *= -1;
+ }
+ int pointDiffY = y - shanY;
+ if (pointDiffY < 0) {
+ pointDiffY *= -1;
+ }
+ pointDiffY *= 1.5;
+ int distance = pointDiffX * pointDiffX + pointDiffY * pointDiffY;
+ if (distance >= kMinDistance) {
+ break;
+ }
+ }
+ int pathSizeDiff = (shanCoords - _mainHero->_currCoords) / 4;
+ int destDir = *(_mainHero->_currDirTab + pathSizeDiff);
+ _secondHero->_destDirection = destDir;
+ int destX = READ_LE_UINT16(shanCoords);
+ int destY = READ_LE_UINT16(shanCoords + 2);
+ _secondHero->_coords = makePath(kSecondHero, _secondHero->_middleX, _secondHero->_middleY, destX, destY);
+ if (_secondHero->_coords != nullptr) {
+ _secondHero->_currCoords = _secondHero->_coords;
+ int delay = shanLen1 - _shanLen;
+ if (delay < 6) {
+ delay = 6;
+ }
+ _secondHero->_moveDelay = delay / 2;
+ _secondHero->_state = Hero::kHeroStateDelayMove;
+ _secondHero->_dirTab = _directionTable;
+ _secondHero->_currDirTab = _directionTable;
+ _directionTable = nullptr;
+ }
+ }
+ }
+ }
+}
+
+byte *PrinceEngine::makePath(int heroId, int currX, int currY, int destX, int destY) {
+ int realDestX = destX;
+ int realDestY = destY;
+ _flags->setFlagValue(Flags::MOVEDESTX, destX);
+ _flags->setFlagValue(Flags::MOVEDESTY, destY);
+
+ int x1 = currX / 2;
+ int y1 = currY / 2;
+ int x2 = destX / 2;
+ int y2 = destY / 2;
+
+ if ((x1 != x2) || (y1 != y2)) {
+ findPoint(x1, y1);
+ if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
+ return nullptr;
+ }
+ if ((x1 != _fpX) || (y1 != _fpY)) {
+ x1 = _fpX;
+ y1 = _fpY;
+ }
+ findPoint(x2, y2);
+ if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
+ return nullptr;
+ }
+ if ((x2 != _fpX) || (y2 != _fpY)) {
+ x2 = _fpX;
+ y2 = _fpY;
+ if (!_flags->getFlagValue(Flags::EXACTMOVE)) {
+ realDestX = x2 * 2;
+ realDestY = y2 * 2;
+ _flags->setFlagValue(Flags::MOVEDESTX, realDestX);
+ _flags->setFlagValue(Flags::MOVEDESTY, realDestY);
+ } else {
+ return nullptr;
+ }
+ }
+
+ if ((x1 == x2) && (y1 == y2)) {
+ if (!heroId) {
+ _mainHero->freeOldMove();
+ _mainHero->_state = Hero::kHeroStateTurn;
+ } else if (heroId == 1) {
+ _secondHero->freeOldMove();
+ _secondHero->_state = Hero::kHeroStateTurn;
+ }
+ return nullptr;
+ }
+
+ int pathLen1 = 0;
+ int pathLen2 = 0;
+ int stX = x1;
+ int stY = y1;
+ int sizeCoords2 = 0;
+
+ if (tracePath(x1, y1, x2, y2)) {
+ allocCoords2();
+ approxPath();
+ sizeCoords2 = _coords2 - _coordsBuf2;
+ for (int i = 0; i < sizeCoords2; i++) {
+ _coordsBuf[i] = _coordsBuf2[i];
+ }
+ _coords = _coordsBuf + sizeCoords2;
+ approxPath();
+ _coordsBuf3 = _coordsBuf2;
+ _coordsBuf2 = nullptr;
+ _coords3 = _coords2;
+ _coords2 = nullptr;
+ pathLen1 = _coords3 - _coordsBuf3;
+ }
+ if (tracePath(x2, y2, x1, y1)) {
+ allocCoords2();
+ approxPath();
+ sizeCoords2 = _coords2 - _coordsBuf2;
+ for (int i = 0; i < sizeCoords2; i++) {
+ _coordsBuf[i] = _coordsBuf2[i];
+ }
+ _coords = _coordsBuf + sizeCoords2;
+ approxPath();
+ pathLen2 = _coords2 - _coordsBuf2;
+ }
+
+ byte *chosenCoordsBuf = _coordsBuf2;
+ byte *choosenCoords = _coords2;
+ int choosenLength = pathLen1;
+ if (pathLen1 < pathLen2) {
+ chosenCoordsBuf = _coordsBuf3;
+ choosenCoords = _coords3;
+ choosenLength = pathLen2;
+ }
+
+ if (choosenLength) {
+ if (chosenCoordsBuf != nullptr) {
+ int tempXBegin = READ_LE_UINT16(chosenCoordsBuf);
+ int tempYBegin = READ_LE_UINT16(chosenCoordsBuf + 2);
+ if (stX != tempXBegin || stY != tempYBegin) {
+ SWAP(chosenCoordsBuf, choosenCoords);
+ chosenCoordsBuf -= 4;
+ byte *tempCoordsBuf = _coordsBuf;
+ while (1) {
+ int cord = READ_LE_UINT32(chosenCoordsBuf);
+ WRITE_LE_UINT32(tempCoordsBuf, cord);
+ tempCoordsBuf += 4;
+ if (chosenCoordsBuf == choosenCoords) {
+ break;
+ }
+ chosenCoordsBuf -= 4;
+ }
+ _coords = tempCoordsBuf;
+ } else {
+ int sizeChoosen = choosenCoords - chosenCoordsBuf;
+ for (int i = 0; i < sizeChoosen; i++) {
+ _coordsBuf[i] = chosenCoordsBuf[i];
+ }
+ _coords = _coordsBuf + sizeChoosen;
+ }
+ WRITE_LE_UINT32(_coords, 0xFFFFFFFF);
+ freeCoords2();
+ freeCoords3();
+ scanDirections();
+
+ byte *tempCoordsBuf = _coordsBuf;
+ byte *tempCoords = _coords;
+ byte *newCoords;
+ if (tempCoordsBuf != tempCoords) {
+ int normCoordsSize = _coords - _coordsBuf + 4;
+ newCoords = (byte *)malloc(normCoordsSize);
+ byte *newCoordsBegin = newCoords;
+ while (tempCoordsBuf != tempCoords) {
+ int newValueX = READ_LE_UINT16(tempCoordsBuf);
+ WRITE_LE_UINT16(newCoords, newValueX * 2);
+ newCoords += 2;
+ int newValueY = READ_LE_UINT16(tempCoordsBuf + 2);
+ WRITE_LE_UINT16(newCoords, newValueY * 2);
+ newCoords += 2;
+ tempCoordsBuf += 4;
+ }
+ WRITE_LE_UINT16(newCoords - 4, realDestX);
+ WRITE_LE_UINT16(newCoords - 2, realDestY);
+ WRITE_LE_UINT32(newCoords, 0xFFFFFFFF);
+ newCoords += 4;
+ _shanLen = (newCoords - newCoordsBegin);
+ _shanLen /= 4;
+ return newCoordsBegin;
+ }
+ }
+ }
+ _coords = _coordsBuf;
+ freeCoords2();
+ freeCoords3();
+ return nullptr;
+ } else {
+ if (!heroId) {
+ _mainHero->freeOldMove();
+ _mainHero->_state = Hero::kHeroStateTurn;
+ } else if (heroId == 1) {
+ _secondHero->freeOldMove();
+ _secondHero->_state = Hero::kHeroStateTurn;
+ }
+ return nullptr;
+ }
+}
+
+void PrinceEngine::allocCoords2() {
+ if (_coordsBuf2 == nullptr) {
+ _coordsBuf2 = (byte *)malloc(kTracePts * 4);
+ _coords2 = _coordsBuf2;
+ }
+}
+
+void PrinceEngine::freeCoords2() {
+ if (_coordsBuf2 != nullptr) {
+ free(_coordsBuf2);
+ _coordsBuf2 = nullptr;
+ _coords2 = nullptr;
+ }
+}
+
+void PrinceEngine::freeCoords3() {
+ if (_coordsBuf3 != nullptr) {
+ free(_coordsBuf3);
+ _coordsBuf3 = nullptr;
+ _coords3 = nullptr;
+ }
+}
+
+void PrinceEngine::openInventoryCheck() {
+ if (!_optionsFlag) {
+ if (_mouseFlag == 1 || _mouseFlag == 2) {
+ if (_mainHero->_visible) {
+ if (!_flags->getFlagValue(Flags::INVALLOWED)) {
+ // 29 - Basement, 50 - Map
+ if (_locationNr != 29 && _locationNr != 50) {
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ if (mousePos.y < 4 && !_showInventoryFlag) {
+ _invCounter++;
+ } else {
+ _invCounter = 0;
+ }
+ if (_invCounter >= _invMaxCount) {
+ inventoryFlagChange(true);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void PrinceEngine::mainLoop() {
+ changeCursor(0);
+ _currentTime = _system->getMillis();
+
+ while (!shouldQuit()) {
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ keyHandler(event);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ leftMouseButton();
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ rightMouseButton();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (shouldQuit()) {
+ return;
+ }
+
+ // for "throw a rock" mini-game
+ mouseWeirdo();
+
+ _interpreter->stepBg();
+ _interpreter->stepFg();
+
+ drawScreen();
+
+ _graph->update(_graph->_frontScreen);
+
+ openInventoryCheck();
+
+ pause();
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
new file mode 100644
index 0000000000..0e5bf97dde
--- /dev/null
+++ b/engines/prince/prince.h
@@ -0,0 +1,668 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_H
+#define PRINCE_H
+
+#include "common/random.h"
+#include "common/system.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/textconsole.h"
+#include "common/rect.h"
+#include "common/events.h"
+#include "common/endian.h"
+#include "common/savefile.h"
+#include "common/serializer.h"
+
+#include "image/bmp.h"
+
+#include "gui/debugger.h"
+
+#include "engines/engine.h"
+#include "engines/util.h"
+
+#include "audio/mixer.h"
+
+#include "video/flic_decoder.h"
+
+#include "prince/mob.h"
+#include "prince/object.h"
+#include "prince/pscr.h"
+
+namespace Prince {
+
+struct PrinceGameDescription;
+struct SavegameHeader;
+
+class PrinceEngine;
+class GraphicsMan;
+class Script;
+class Interpreter;
+class InterpreterFlags;
+class Debugger;
+class MusicPlayer;
+class VariaTxt;
+class Cursor;
+class MhwanhDecoder;
+class Font;
+class Hero;
+class Animation;
+class Room;
+class Pscr;
+
+struct Text {
+ const char *_str;
+ uint16 _x, _y;
+ uint16 _time;
+ uint32 _color;
+
+ Text() : _str(nullptr), _x(0), _y(0), _time(0), _color(255){
+ }
+};
+
+struct AnimListItem {
+ uint16 _type; // type of animation - for background anims RND of frame
+ uint16 _fileNumber;
+ uint16 _startPhase; // first phase number
+ uint16 _endPhase;
+ uint16 _loopPhase;
+ int16 _x;
+ int16 _y;
+ uint16 _loopType;
+ uint16 _nextAnim; // number of animation to do for loop = 3
+ uint16 _flags; // byte 0 - draw masks, byte 1 - draw in front of mask, byte 2 - load but turn off drawing
+ bool loadFromStream(Common::SeekableReadStream &stream);
+};
+
+struct BAS {
+ int32 _type; // type of sequence
+ int32 _data; // additional data
+ int32 _anims; // number of animations
+ int32 _current; // actual number of animation
+ int32 _counter; // time counter for animation
+ int32 _currRelative; //actual relative number for animation
+ int32 _data2; // additional data for measurements
+};
+
+const int kStructSizeBAS = 28;
+
+struct BASA {
+ int16 _num; // animation number
+ int16 _start; // initial frame
+ int16 _end; // final frame
+ //int16 _pad; // fulfilment to 8 bytes
+};
+
+const int kStructSizeBASA = 8;
+
+// background and normal animation
+struct Anim {
+ BASA _basaData;
+ int32 _addr; //animation adress
+ int16 _usage;
+ int16 _state; // state of animation: 0 - turning on, 1 - turning off
+ int16 _flags;
+ int16 _frame; // number of phase to show
+ int16 _lastFrame; // last phase
+ int16 _loopFrame; // first frame of loop
+ int16 _showFrame; // actual visible frame of animation
+ int16 _loopType; // type of loop (0 - last frame; 1 - normal loop (begin from _loopFrame); 2 - no loop; 3 - load new animation)
+ int16 _nextAnim; // number of next animation to load after actual
+ int16 _x;
+ int16 _y;
+ int32 _currFrame;
+ int16 _currX;
+ int16 _currY;
+ int16 _currW;
+ int16 _currH;
+ int16 _packFlag;
+ int32 _currShadowFrame;
+ int16 _packShadowFlag;
+ int32 _shadowBack;
+ int16 _relX;
+ int16 _relY;
+ Animation *_animData;
+ Animation *_shadowData;
+
+ enum AnimOffsets {
+ kAnimState = 10,
+ kAnimFrame = 14,
+ kAnimLastFrame = 16,
+ kAnimX = 26
+ };
+
+ int16 getAnimData(Anim::AnimOffsets offset) {
+ switch (offset) {
+ case kAnimState:
+ return _state;
+ case kAnimFrame:
+ return _frame + 1; // fix for location 30 - man with a dog animation
+ case kAnimX:
+ return _x;
+ default:
+ error("getAnimData() - Wrong offset type: %d", (int) offset);
+ }
+ }
+
+ void setAnimData(Anim::AnimOffsets offset, int16 value) {
+ if (offset == kAnimX) {
+ _x = value;
+ } else {
+ error("setAnimData() - Wrong offset: %d, value: %d", (int) offset, value);
+ }
+ }
+};
+
+struct BackgroundAnim {
+ BAS _seq;
+ Common::Array<Anim> backAnims;
+};
+
+enum AnimType {
+ kBackgroundAnimation,
+ kNormalAnimation
+};
+
+// Nak (PL - Nakladka)
+struct Mask {
+ uint16 _state; // visible / invisible
+ int16 _flags; // turning on / turning off of an mask
+ int16 _x1;
+ int16 _y1;
+ int16 _x2;
+ int16 _y2;
+ int16 _z;
+ int16 _number; // number of mask for background recreating
+ int16 _width;
+ int16 _height;
+ byte *_data;
+
+ int16 getX() const {
+ return READ_LE_UINT16(_data);
+ }
+
+ int16 getY() const {
+ return READ_LE_UINT16(_data + 2);
+ }
+
+ int16 getWidth() const {
+ return READ_LE_UINT16(_data + 4);
+ }
+
+ int16 getHeight() const {
+ return READ_LE_UINT16(_data + 6);
+ }
+
+ byte *getMask() const {
+ return (byte *)(_data + 8);
+ }
+};
+
+struct InvItem {
+ int _x;
+ int _y;
+ Graphics::Surface *_surface;
+ Graphics::Surface *getSurface() const { return _surface; }
+};
+
+struct DrawNode {
+ int posX;
+ int posY;
+ int posZ;
+ int32 width;
+ int32 height;
+ int32 scaleValue;
+ Graphics::Surface *s;
+ Graphics::Surface *originalRoomSurface;
+ void *data;
+ void (*drawFunction)(Graphics::Surface *, DrawNode *);
+};
+
+struct DebugChannel {
+
+enum Type {
+ kScript,
+ kEngine
+};
+
+};
+
+class PrinceEngine : public Engine {
+protected:
+ Common::Error run();
+
+public:
+ PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc);
+ virtual ~PrinceEngine();
+
+ virtual bool hasFeature(EngineFeature f) const;
+ virtual bool canSaveGameStateCurrently();
+ virtual bool canLoadGameStateCurrently();
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+ virtual Common::Error loadGameState(int slot);
+
+ static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+ Common::String generateSaveName(int slot);
+ void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header);
+ void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream);
+ bool loadGame(int slotNumber);
+ void resetGame();
+
+ int32 _creditsDataSize;
+ byte *_creditsData;
+ void scrollCredits();
+
+ int getGameType() const;
+ const char *getGameId() const;
+ uint32 getFeatures() const;
+ Common::Language getLanguage() const;
+
+ const PrinceGameDescription *_gameDescription;
+ Video::FlicDecoder _flicPlayer;
+ const Graphics::Surface *_flcFrameSurface;
+ VariaTxt *_variaTxt;
+
+ uint32 _talkTxtSize;
+ byte *_talkTxt;
+
+ bool loadLocation(uint16 locationNr);
+ bool loadAnim(uint16 animNr, bool loop);
+ bool loadVoice(uint32 textSlot, uint32 sampleSlot, const Common::String &name);
+ bool loadSample(uint32 sampleSlot, const Common::String &name);
+ bool loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName);
+ bool loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2);
+ bool loadTrans(byte *transTable, const char *resourceName);
+ bool loadMobPriority(const char *resourceName);
+
+ bool loadMusic(int musNumber);
+ void stopMusic();
+
+ void playSample(uint16 sampleId, uint16 loopType);
+ void stopSample(uint16 sampleId);
+ void stopAllSamples();
+ void freeSample(uint16 sampleId);
+ void freeAllSamples();
+
+ void setVoice(uint16 slot, uint32 sampleSlot, uint16 flag);
+
+ virtual GUI::Debugger *getDebugger();
+
+ void changeCursor(uint16 curId);
+ void printAt(uint32 slot, uint8 color, char *s, uint16 x, uint16 y);
+ int calcTextLines(const char *s);
+ int calcTextTime(int numberOfLines);
+ void correctStringDEU(char *s);
+
+ static const uint8 kMaxTexts = 32;
+ Text _textSlots[kMaxTexts];
+
+ Hero *_mainHero;
+ Hero *_secondHero;
+
+ enum HeroId {
+ kMainHero,
+ kSecondHero
+ };
+
+ int _mouseFlag;
+ uint32 _currentTime;
+ uint16 _locationNr;
+ uint16 _sceneWidth;
+ int32 _picWindowX;
+ int32 _picWindowY;
+
+ Image::BitmapDecoder *_roomBmp;
+ MhwanhDecoder *_suitcaseBmp;
+ Room *_room;
+ Script *_script;
+ InterpreterFlags *_flags;
+ Interpreter *_interpreter;
+ GraphicsMan *_graph;
+ uint8 _currentMidi;
+ byte *_zoomBitmap;
+ byte *_shadowBitmap;
+ byte *_transTable;
+
+ int16 _scaleValue; // scale for hero or special shadow animation
+ int16 _lightX; // for hero shadow
+ int16 _lightY;
+ int32 _shadScaleValue;
+ int32 _shadLineLen;
+ byte *_shadowLine;
+ void setShadowScale(int32 shadowScale);
+ static void plotShadowLinePoint(int x, int y, int color, void *data);
+
+ static const int16 kFPS = 15;
+ static const int32 kIntMax = 2147483647;
+
+ static const int16 kMaxPicWidth = 1280;
+ static const int16 kMaxPicHeight = 480;
+ static const int16 kZoomStep = 4;
+ static const int32 kZoomBitmapLen = kMaxPicHeight / kZoomStep * kMaxPicWidth / kZoomStep;
+ static const int32 kShadowBitmapSize = kMaxPicWidth * kMaxPicHeight / 8;
+ static const int16 kShadowLineArraySize = 2 * 1280 * 4;
+ static const int16 kZoomBitmapWidth = kMaxPicWidth / kZoomStep;
+ static const int16 kZoomBitmapHeight = kMaxPicHeight / kZoomStep;
+ static const int16 kNormalWidth = 640;
+ static const int16 kNormalHeight = 480;
+ static const int32 kTransTableSize = 256 * 256;
+
+ static const int kMaxNormAnims = 64;
+ static const int kMaxBackAnims = 64;
+ static const int kMaxObjects = 64;
+ static const int kMaxMobs = 64;
+
+ Common::Array<DrawNode> _drawNodeList;
+ Common::Array<AnimListItem> _animList;
+ Common::Array<BackgroundAnim> _backAnimList;
+ Common::Array<Anim> _normAnimList;
+ Common::Array<Mob> _mobList;
+ Common::Array<uint32> _mobPriorityList;
+ Common::Array<Mask> _maskList;
+ Common::Array<Object *> _objList;
+ uint16 *_objSlot;
+
+ void freeNormAnim(int slot);
+ void freeAllNormAnims();
+ void removeSingleBackAnim(int slot);
+
+ Common::RandomSource _randomSource;
+
+ void checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z);
+ void insertMasks(Graphics::Surface *originalRoomSurface);
+ void showMask(int maskNr, Graphics::Surface *originalRoomSurface);
+ void clsMasks();
+
+ void grabMap();
+
+ int _selectedMob; // number of selected Mob / inventory item
+ int _selectedItem; // number of item on mouse cursor
+ int _selectedMode;
+ int _currentPointerNumber;
+
+ static const int16 kMaxInv = 90; // max amount of inventory items in whole game
+ static const int16 kMaxItems = 30; // size of inventory
+
+ uint32 _invTxtSize;
+ byte *_invTxt;
+
+ Graphics::Surface *_optionsPic;
+ Graphics::Surface *_optionsPicInInventory;
+
+ bool _optionsFlag;
+ int _optionEnabled;
+ int _optionsMob;
+ int _optionsX;
+ int _optionsY;
+ int _optionsWidth;
+ int _optionsHeight;
+ int _invOptionsWidth;
+ int _invOptionsHeight;
+ int _optionsStep;
+ int _invOptionsStep;
+ int _optionsNumber;
+ int _invOptionsNumber;
+ int _optionsColor1; // color for non-selected options
+ int _optionsColor2; // color for selected option
+
+ bool _showInventoryFlag;
+ int _invExamY;
+ bool _inventoryBackgroundRemember;
+ int _invLineX;
+ int _invLineY;
+ int _invLine; // number of items in one line
+ int _invLines; // number of lines with inventory items
+ int _invLineW;
+ int _invLineH;
+ int _maxInvW;
+ int _maxInvH;
+ int _invLineSkipX;
+ int _invLineSkipY;
+ int _invX1;
+ int _invY1;
+ int _invWidth;
+ int _invHeight;
+ bool _invCurInside;
+ int _mst_shadow;
+ int _mst_shadow2; // blinking after adding new item
+ int _candleCounter; // special counter for candle inventory item
+ int _invMaxCount; // time to turn inventory on
+ int _invCounter; // turning on counter
+
+ void inventoryFlagChange(bool inventoryState);
+ bool loadAllInv();
+ void rememberScreenInv();
+ void prepareInventoryToView();
+ void drawInvItems();
+ void displayInventory();
+ void addInv(int heroId, int item, bool addItemQuiet);
+ void remInv(int heroId, int item);
+ void clearInv(int heroId);
+ void swapInv(int heroId);
+ void addInvObj();
+ void makeInvCursor(int itemNr);
+ void enableOptions(bool checkType);
+ void checkOptions();
+ void checkInvOptions();
+ void openInventoryCheck();
+
+ void leftMouseButton();
+ void rightMouseButton();
+ void inventoryLeftMouseButton();
+ void inventoryRightMouseButton();
+ void dialogLeftMouseButton(byte *string, int dialogSelected);
+
+ uint32 _dialogDatSize;
+ byte *_dialogDat;
+ byte *_dialogData; // on, off flags for lines of dialog text
+
+ byte *_dialogBoxAddr[32]; // adresses of dialog windows
+ byte *_dialogOptAddr[32]; // adresses of dialog options
+ int _dialogOptLines[4 * 32]; // numbers of initial dialog lines
+
+ byte *_dialogText;
+ int _dialogLines;
+ bool _dialogFlag;
+ int _dialogWidth;
+ int _dialogHeight;
+ int _dialogLineSpace;
+ int _dialogColor1; // color for non-selected options
+ int _dialogColor2; // color for selected option
+ Graphics::Surface *_dialogImage;
+
+ void createDialogBox(int dialogBoxNr);
+ void dialogRun();
+ void talkHero(int slot);
+ void doTalkAnim(int animNumber, int slot, AnimType animType);
+
+ static const uint8 zoomInStep = 8;
+ void initZoomIn(int slot);
+ void initZoomOut(int slot);
+ void doZoomIn(int slot);
+ void doZoomOut(int slot);
+ void freeZoomObject(int slot);
+
+ static const uint8 kFadeStep = 4;
+ void blackPalette();
+ void setPalette(const byte *palette);
+
+ int getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY);
+
+ // 'Throw a rock' mini-game:
+ static const int16 kCurveLen = 17;
+ static const int kCelStep = 4;
+ int16 *_curveData;
+ int _curvPos;
+ void makeCurve();
+ void getCurve();
+ void mouseWeirdo();
+
+ static const uint16 kPowerBarPosX = 288;
+ static const uint16 kPowerBarPosY = 430;
+ static const uint8 kPowerBarWidth = 64;
+ static const uint8 kPowerBarHeight = 16;
+ static const uint8 kPowerBarBackgroundColor = 0;
+ static const uint16 kPowerBarGreenPosY = 434;
+ static const uint8 kPowerBarGreenColor1 = 202;
+ static const uint8 kPowerBarGreenColor2 = 235;
+ static const uint8 kPowerBarGreenHeight = 8;
+ void showPower();
+
+ // Pathfinding
+ static const int16 kPathGridStep = 2;
+ static const int32 kPathBitmapLen = (kMaxPicHeight / kPathGridStep * kMaxPicWidth / kPathGridStep) / 8;
+ static const int32 kTracePts = 8000;
+ static const int32 kPBW = kMaxPicWidth / 16; // PathBitmapWidth
+ static const int kMinDistance = 2500;
+
+ byte *_roomPathBitmap; // PL - Sala
+ byte *_roomPathBitmapTemp; // PL - SSala
+ byte *_coordsBufEnd;
+ byte *_coordsBuf; // optimal path
+ byte *_coords; // last path point adress from coordsBuf
+ byte *_coordsBuf2;
+ byte *_coords2;
+ byte *_coordsBuf3;
+ byte *_coords3;
+ int _traceLineLen;
+ bool _traceLineFirstPointFlag; // if plotTraceLine after first point
+ bool _tracePointFirstPointFlag; // if plotTracePoint after first point
+ byte *_directionTable;
+ int _shanLen;
+
+ byte *_checkBitmapTemp;
+ byte *_checkBitmap;
+ int _checkMask;
+ int _checkX;
+ int _checkY;
+
+ byte *_rembBitmapTemp;
+ byte *_rembBitmap;
+ int _rembMask;
+ int _rembX;
+ int _rembY;
+
+ int _fpX;
+ int _fpY;
+
+ int drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data);
+ bool loadPath(const char *resourceName);
+ byte *makePath(int heroId, int currX, int currY, int destX, int destY);
+ void findPoint(int x, int y);
+ int getPixelAddr(byte *pathBitmap, int x, int y);
+ static int plotTraceLine(int x, int y, void *data);
+ void specialPlotInside(int x, int y);
+ bool tracePath(int x1, int y1, int x2, int y2);
+ Direction makeDirection(int x1, int y1, int x2, int y2);
+ void specialPlot(int x, int y);
+ void specialPlot2(int x, int y);
+ void allocCoords2();
+ void freeCoords2();
+ void freeCoords3();
+ static int plotTracePoint(int x, int y, void *data);
+ void specialPlotInside2(int x, int y);
+ void approxPath();
+ void freeDirectionTable();
+ void scanDirections();
+ int scanDirectionsFindNext(byte *coords, int xDiff, int yDiff);
+ void moveShandria();
+ void walkTo();
+ void moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag);
+
+ int leftDownDir();
+ int leftDir();
+ int leftUpDir();
+ int rightDownDir();
+ int rightDir();
+ int rightUpDir();
+ int upLeftDir();
+ int upDir();
+ int upRightDir();
+ int downLeftDir();
+ int downDir();
+ int downRightDir();
+
+ int cpe();
+ int checkLeftDownDir();
+ int checkLeftDir();
+ int checkDownDir();
+ int checkUpDir();
+ int checkRightDir();
+ int checkLeftUpDir();
+ int checkRightDownDir();
+ int checkRightUpDir();
+
+private:
+ bool playNextFLCFrame();
+ void keyHandler(Common::Event event);
+ int checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList);
+ void drawScreen();
+ void showTexts(Graphics::Surface *screen);
+ void init();
+ void showLogo();
+ void showAnim(Anim &anim);
+ void showNormAnims();
+ void setBackAnim(Anim &backAnim);
+ void showBackAnims();
+ void clearBackAnimList();
+ bool spriteCheck(int sprWidth, int sprHeight, int destX, int destY);
+ void showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ);
+ void showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ);
+ void showObjects();
+ void showParallax();
+ static bool compareDrawNodes(DrawNode d1, DrawNode d2);
+ void runDrawNodes();
+ void makeShadowTable(int brightness);
+ void pause();
+ void pause2();
+
+ uint32 getTextWidth(const char *s);
+ void debugEngine(const char *s, ...);
+
+ uint8 _cursorNr;
+
+ Common::RandomSource *_rnd;
+ Cursor *_cursor1;
+ Graphics::Surface *_cursor2;
+ Cursor *_cursor3;
+ Debugger *_debugger;
+ Font *_font;
+ MusicPlayer *_midiPlayer;
+
+ static const int kMaxSamples = 60;
+ Audio::RewindableAudioStream *_audioStream[kMaxSamples];
+ Audio::SoundHandle _soundHandle[kMaxSamples];
+
+ Common::Array<PScr *> _pscrList;
+ Common::Array<InvItem> _allInvList;
+ Common::Array<Mob> _invMobList;
+
+ bool _flicLooped;
+
+ void mainLoop();
+
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/pscr.cpp b/engines/prince/pscr.cpp
new file mode 100644
index 0000000000..d9d36a3356
--- /dev/null
+++ b/engines/prince/pscr.cpp
@@ -0,0 +1,75 @@
+/* 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 "common/archive.h"
+#include "common/stream.h"
+
+#include "prince/pscr.h"
+
+namespace Prince {
+
+PScr::PScr() : _x(0), _y(0), _step(0), _surface(nullptr)
+{
+}
+
+PScr::~PScr() {
+ if (_surface != nullptr) {
+ _surface->free();
+ delete _surface;
+ _surface = nullptr;
+ }
+}
+
+void PScr::loadSurface(Common::SeekableReadStream &stream) {
+ stream.skip(4);
+ int width = stream.readUint16LE();
+ int height = stream.readUint16LE();
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int h = 0; h < _surface->h; h++) {
+ stream.read(_surface->getBasePtr(0, h), _surface->w);
+ }
+}
+
+bool PScr::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+ uint16 file = stream.readUint16LE();
+ if (file == 0xFFFF) {
+ return false;
+ }
+ _x = stream.readUint16LE();
+ _y = stream.readUint16LE();
+ _step = stream.readUint16LE();
+
+ const Common::String pscrStreamName = Common::String::format("PS%02d", file);
+ Common::SeekableReadStream *pscrStream = SearchMan.createReadStreamForMember(pscrStreamName);
+ if (pscrStream != nullptr) {
+ loadSurface(*pscrStream);
+ }
+ delete pscrStream;
+ stream.seek(pos + 12); // size of PScrList struct
+
+ return true;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/pscr.h b/engines/prince/pscr.h
new file mode 100644
index 0000000000..d59fa37d81
--- /dev/null
+++ b/engines/prince/pscr.h
@@ -0,0 +1,48 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_PSCR_H
+#define PRINCE_PSCR_H
+
+#include "graphics/surface.h"
+
+namespace Prince {
+
+class PScr {
+public:
+ PScr();
+ ~PScr();
+ int16 _x;
+ int16 _y;
+ int16 _step;
+ static const int16 kPScrZ = 1000;
+
+ bool loadFromStream(Common::SeekableReadStream &stream);
+ Graphics::Surface *getSurface() const { return _surface; }
+private:
+ void loadSurface(Common::SeekableReadStream &stream);
+ Graphics::Surface *_surface;
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/resource.h b/engines/prince/resource.h
new file mode 100644
index 0000000000..b1fbd9c4f0
--- /dev/null
+++ b/engines/prince/resource.h
@@ -0,0 +1,100 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_RESOURCE_H
+#define PRINCE_RESOURCE_H
+
+#include "common/stream.h"
+#include "common/archive.h"
+#include "common/debug-channels.h"
+#include "common/ptr.h"
+
+namespace Prince {
+
+namespace Resource {
+
+ template <typename T>
+ bool loadFromStream(T &resource, Common::SeekableReadStream &stream) {
+ return resource.loadStream(stream);
+ }
+
+ template<typename T>
+ bool loadResource(T *resource, const char *resourceName, bool required) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ return loadFromStream(*resource, *stream);
+ }
+
+ template <typename T>
+ bool loadResource(Common::Array<T> &array, Common::SeekableReadStream &stream, bool required = true) {
+ T t;
+ while (t.loadFromStream(stream))
+ array.push_back(t);
+
+ return true;
+ }
+
+
+ template <typename T>
+ bool loadResource(Common::Array<T> &array, const char *resourceName, bool required = true) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ return loadResource(array, *stream, required);
+ }
+
+ template <typename T>
+ bool loadResource(Common::Array<T *> &array, const char *resourceName, bool required = true) {
+
+ Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ // FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initiailzed object
+ while (true) {
+ T* t = new T();
+ if (!t->loadFromStream(*stream)) {
+ delete t;
+ break;
+ }
+ array.push_back(t);
+ }
+ return true;
+ }
+
+}
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/saveload.cpp b/engines/prince/saveload.cpp
new file mode 100644
index 0000000000..39a4002b40
--- /dev/null
+++ b/engines/prince/saveload.cpp
@@ -0,0 +1,514 @@
+/* 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 "prince/prince.h"
+#include "prince/graphics.h"
+#include "prince/detection.h"
+#include "prince/flags.h"
+#include "prince/script.h"
+#include "prince/hero.h"
+
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/config-manager.h"
+#include "common/memstream.h"
+
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+
+namespace Prince {
+
+#define kBadSVG 99
+#define kSavegameVersion 1
+#define kSavegameStrSize 14
+#define kSavegameStr "SCUMMVM_PRINCE"
+
+class InterpreterFlags;
+class Interpreter;
+
+struct SavegameHeader {
+ uint8 version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+ int saveYear, saveMonth, saveDay;
+ int saveHour, saveMinutes;
+};
+
+int PrinceMetaEngine::getMaximumSaveSlot() const {
+ return 99;
+}
+
+SaveStateList PrinceMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String pattern = target;
+ pattern += ".???";
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
+
+ SaveStateList saveList;
+ 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
+ int slotNum = atoi(filename->c_str() + filename->size() - 3);
+
+ if (slotNum >= 0 && slotNum <= 99) {
+
+ Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
+ if (file) {
+ Prince::SavegameHeader header;
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[kSavegameStrSize + 1];
+ file->read(buffer, kSavegameStrSize + 1);
+
+ if (!strncmp(buffer, kSavegameStr, kSavegameStrSize + 1)) {
+ // Valid savegame
+ if (Prince::PrinceEngine::readSavegameHeader(file, header)) {
+ saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
+ if (header.thumbnail) {
+ header.thumbnail->free();
+ delete header.thumbnail;
+ }
+ }
+ } else {
+ // Must be an original format savegame
+ saveList.push_back(SaveStateDescriptor(slotNum, "Unknown"));
+ }
+
+ delete file;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+SaveStateDescriptor PrinceMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (f) {
+ Prince::SavegameHeader header;
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[kSavegameStrSize + 1];
+ f->read(buffer, kSavegameStrSize + 1);
+
+ bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) &&
+ Prince::PrinceEngine::readSavegameHeader(f, header);
+ delete f;
+
+ if (!hasHeader) {
+ // Original savegame perhaps?
+ SaveStateDescriptor desc(slot, "Unknown");
+ return desc;
+ } else {
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header.saveName);
+ desc.setThumbnail(header.thumbnail);
+ desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
+ desc.setSaveTime(header.saveHour, header.saveMinutes);
+
+ return desc;
+ }
+ }
+
+ return SaveStateDescriptor();
+}
+
+bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
+ header.thumbnail = nullptr;
+
+ // Get the savegame version
+ header.version = in->readByte();
+ if (header.version > kSavegameVersion)
+ return false;
+
+ // Read in the string
+ header.saveName.clear();
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0')
+ header.saveName += ch;
+
+ // Get the thumbnail
+ header.thumbnail = Graphics::loadThumbnail(*in);
+ if (!header.thumbnail)
+ return false;
+
+ // Read in save date/time
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
+ header.saveMinutes = in->readSint16LE();
+
+ return true;
+}
+
+void PrinceMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s.%03d", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+// TODO
+bool PrinceEngine::canSaveGameStateCurrently() {
+ return true;
+}
+
+// TODO
+bool PrinceEngine::canLoadGameStateCurrently() {
+ return true;
+}
+
+Common::Error PrinceEngine::saveGameState(int slot, const Common::String &desc) {
+ // Set up the serializer
+ Common::String slotName = generateSaveName(slot);
+ Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(slotName);
+
+ // Write out the ScummVM savegame header
+ SavegameHeader header;
+ header.saveName = desc;
+ header.version = kSavegameVersion;
+ writeSavegameHeader(saveFile, header);
+
+ // Write out the data of the savegame
+ syncGame(nullptr, saveFile);
+
+ // Finish writing out game data
+ saveFile->finalize();
+ delete saveFile;
+
+ return Common::kNoError;
+}
+
+Common::String PrinceEngine::generateSaveName(int slot) {
+ return Common::String::format("%s.%03d", _targetName.c_str(), slot);
+}
+
+void PrinceEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header) {
+ // Write out a savegame header
+ out->write(kSavegameStr, kSavegameStrSize + 1);
+
+ out->writeByte(kSavegameVersion);
+
+ // Write savegame name
+ out->write(header.saveName.c_str(), header.saveName.size() + 1);
+
+ // Get the active palette
+ uint8 thumbPalette[256 * 3];
+ _system->getPaletteManager()->grabPalette(thumbPalette, 0, 256);
+
+ // Create a thumbnail and save it
+ Graphics::Surface *thumb = new Graphics::Surface();
+ Graphics::Surface *s = _graph->_frontScreen; // check inventory / map etc..
+ ::createThumbnail(thumb, (const byte *)s->getPixels(), s->w, s->h, thumbPalette);
+ Graphics::saveThumbnail(*out, *thumb);
+ thumb->free();
+ delete thumb;
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ out->writeSint16LE(td.tm_year + 1900);
+ out->writeSint16LE(td.tm_mon + 1);
+ out->writeSint16LE(td.tm_mday);
+ out->writeSint16LE(td.tm_hour);
+ out->writeSint16LE(td.tm_min);
+}
+
+void PrinceEngine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream) {
+ int emptyRoom = 0x00;
+ int normRoom = 0xFF;
+ byte endInv = 0xFF;
+
+ Common::Serializer s(readStream, writeStream);
+
+ if (s.isSaving()) {
+ // Flag values
+ for (int i = 0; i < _flags->kMaxFlags; i++) {
+ uint32 value = _flags->getFlagValue((Flags::Id)(_flags->kFlagMask + i));
+ s.syncAsUint32LE(value);
+ }
+
+ // Dialog data
+ for (uint32 i = 0; i < _dialogDatSize; i++) {
+ byte value = _dialogDat[i];
+ s.syncAsByte(value);
+ }
+
+ // Location number
+ s.syncAsUint16LE(_locationNr);
+
+ // Rooms
+ for (int roomId = 0; roomId < _script->kMaxRooms; roomId++) {
+ Room *room = new Room();
+ room->loadRoom(_script->getRoomOffset(roomId));
+
+ if (room->_mobs) {
+ s.syncAsByte(normRoom);
+ } else {
+ s.syncAsByte(emptyRoom);
+ delete room;
+ continue;
+ }
+
+ // Mobs
+ for (int mobId = 0; mobId < kMaxMobs; mobId++) {
+ byte value = _script->getMobVisible(room->_mobs, mobId);
+ s.syncAsByte(value);
+ }
+
+ // Background animations
+ for (int backAnimSlot = 0; backAnimSlot < kMaxBackAnims; backAnimSlot++) {
+ uint32 value = _script->getBackAnimId(room->_backAnim, backAnimSlot);
+ s.syncAsUint32LE(value);
+ }
+
+ // Objects
+ for (int objectSlot = 0; objectSlot < kMaxObjects; objectSlot++) {
+ byte value = _script->getObjId(room->_obj, objectSlot);
+ s.syncAsByte(value);
+ }
+
+ delete room;
+ }
+
+ // Main hero
+ s.syncAsUint16LE(_mainHero->_visible);
+ s.syncAsUint16LE(_mainHero->_middleX);
+ s.syncAsUint16LE(_mainHero->_middleY);
+ s.syncAsUint16LE(_mainHero->_lastDirection);
+ s.syncAsUint32LE(_mainHero->_color);
+ s.syncAsUint16LE(_mainHero->_maxBoredom);
+ s.syncAsUint32LE(_mainHero->_animSetNr);
+
+ for (uint inv1Slot = 0; inv1Slot < _mainHero->_inventory.size(); inv1Slot++) {
+ s.syncAsByte(_mainHero->_inventory[inv1Slot]);
+ }
+ s.syncAsByte(endInv);
+
+ for (uint inv2Slot = 0; inv2Slot < _mainHero->_inventory2.size(); inv2Slot++) {
+ s.syncAsByte(_mainHero->_inventory2[inv2Slot]);
+ }
+ s.syncAsByte(endInv);
+
+ // Second hero
+ s.syncAsUint16LE(_secondHero->_visible);
+ s.syncAsUint16LE(_secondHero->_middleX);
+ s.syncAsUint16LE(_secondHero->_middleY);
+ s.syncAsUint16LE(_secondHero->_lastDirection);
+ s.syncAsUint32LE(_secondHero->_color);
+ s.syncAsUint16LE(_secondHero->_maxBoredom);
+ s.syncAsUint32LE(_secondHero->_animSetNr);
+
+ for (uint inv1Slot = 0; inv1Slot < _secondHero->_inventory.size(); inv1Slot++) {
+ s.syncAsByte(_secondHero->_inventory[inv1Slot]);
+ }
+ s.syncAsByte(endInv);
+
+ for (uint inv2Slot = 0; inv2Slot < _secondHero->_inventory2.size(); inv2Slot++) {
+ s.syncAsByte(_secondHero->_inventory2[inv2Slot]);
+ }
+ s.syncAsByte(endInv);
+
+ } else {
+ // Cursor reset
+ changeCursor(1);
+ _currentPointerNumber = 1;
+
+ // Flag values
+ for (int i = 0; i < _flags->kMaxFlags; i++) {
+ uint32 value = 0;
+ s.syncAsUint32LE(value);
+ _flags->setFlagValue((Flags::Id)(_flags->kFlagMask + i), value);
+ }
+
+ // Dialog data
+ for (uint32 i = 0; i < _dialogDatSize; i++) {
+ byte value = 0;
+ s.syncAsByte(value);
+ _dialogDat[i] = value;
+ }
+
+ // Location number
+ int restoreRoom = 0;
+ s.syncAsUint16LE(restoreRoom);
+ _flags->setFlagValue(Flags::RESTOREROOM, restoreRoom);
+
+ // Rooms
+ for (int roomId = 0; roomId < _script->kMaxRooms; roomId++) {
+ Room *room = new Room();
+ room->loadRoom(_script->getRoomOffset(roomId));
+
+ byte roomType = emptyRoom;
+ s.syncAsByte(roomType);
+ if (roomType == emptyRoom) {
+ delete room;
+ continue;
+ }
+
+ // Mobs
+ for (int mobId = 0; mobId < kMaxMobs; mobId++) {
+ byte value = 0;
+ s.syncAsByte(value);
+ _script->setMobVisible(room->_mobs, mobId, value);
+ }
+
+ // Background animations
+ for (int backAnimSlot = 0; backAnimSlot < kMaxBackAnims; backAnimSlot++) {
+ uint32 value = 0;
+ s.syncAsUint32LE(value);
+ _script->setBackAnimId(room->_backAnim, backAnimSlot, value);
+ }
+
+ // Objects
+ for (int objectSlot = 0; objectSlot < kMaxObjects; objectSlot++) {
+ byte value = 0;
+ s.syncAsByte(value);
+ _script->setObjId(room->_obj, objectSlot, value);
+ }
+
+ delete room;
+ }
+
+ // Main hero
+ s.syncAsUint16LE(_mainHero->_visible);
+ s.syncAsUint16LE(_mainHero->_middleX);
+ s.syncAsUint16LE(_mainHero->_middleY);
+ s.syncAsUint16LE(_mainHero->_lastDirection);
+ s.syncAsUint32LE(_mainHero->_color);
+ s.syncAsUint16LE(_mainHero->_maxBoredom);
+ s.syncAsUint32LE(_mainHero->_animSetNr);
+ _mainHero->loadAnimSet(_mainHero->_animSetNr);
+
+ _mainHero->_inventory.clear();
+ byte invId = endInv;
+ while (1) {
+ s.syncAsByte(invId);
+ if (invId == endInv) {
+ break;
+ }
+ _mainHero->_inventory.push_back(invId);
+ }
+
+ _mainHero->_inventory2.clear();
+ invId = endInv;
+ while (1) {
+ s.syncAsByte(invId);
+ if (invId == endInv) {
+ break;
+ }
+ _mainHero->_inventory2.push_back(invId);
+ }
+
+ // Second hero
+ s.syncAsUint16LE(_secondHero->_visible);
+ s.syncAsUint16LE(_secondHero->_middleX);
+ s.syncAsUint16LE(_secondHero->_middleY);
+ s.syncAsUint16LE(_secondHero->_lastDirection);
+ s.syncAsUint32LE(_secondHero->_color);
+ s.syncAsUint16LE(_secondHero->_maxBoredom);
+ s.syncAsUint32LE(_secondHero->_animSetNr);
+ _secondHero->loadAnimSet(_secondHero->_animSetNr);
+
+ _secondHero->_inventory.clear();
+ invId = endInv;
+ while (1) {
+ s.syncAsByte(invId);
+ if (invId == endInv) {
+ break;
+ }
+ _secondHero->_inventory.push_back(invId);
+ }
+
+ _secondHero->_inventory2.clear();
+ invId = endInv;
+ while (1) {
+ s.syncAsByte(invId);
+ if (invId == endInv) {
+ break;
+ }
+ _secondHero->_inventory2.push_back(invId);
+ }
+
+ // Script
+ _interpreter->setBgOpcodePC(0);
+ _interpreter->setFgOpcodePC(_script->_scriptInfo.restoreGame);
+
+ }
+}
+
+Common::Error PrinceEngine::loadGameState(int slot) {
+ if (!loadGame(slot)) {
+ return Common::kReadingFailed;
+ }
+ return Common::kNoError;
+}
+
+bool PrinceEngine::loadGame(int slotNumber) {
+ Common::MemoryReadStream *readStream;
+
+ // Open up the savegame file
+ Common::String slotName = generateSaveName(slotNumber);
+ Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slotName);
+
+ // Read the data into a data buffer
+ int size = saveFile->size();
+ byte *dataBuffer = (byte *)malloc(size);
+ saveFile->read(dataBuffer, size);
+ readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES);
+ delete saveFile;
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[kSavegameStrSize + 1];
+ readStream->read(buffer, kSavegameStrSize + 1);
+
+ if (strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) != 0) {
+ delete readStream;
+ return false;
+ } else {
+ SavegameHeader saveHeader;
+
+ if (!readSavegameHeader(readStream, saveHeader)) {
+ delete readStream;
+ return false;
+ }
+
+ // Delete the thumbnail
+ saveHeader.thumbnail->free();
+ delete saveHeader.thumbnail;
+ }
+
+ // Get in the savegame
+ syncGame(readStream, nullptr);
+ delete readStream;
+
+ // TODO
+ //syncSpeechSettings();
+
+ return true;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp
new file mode 100644
index 0000000000..d1a0034940
--- /dev/null
+++ b/engines/prince/script.cpp
@@ -0,0 +1,2071 @@
+/* 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 "prince/script.h"
+#include "prince/prince.h"
+#include "prince/flags.h"
+#include "prince/variatxt.h"
+#include "prince/font.h"
+#include "prince/hero.h"
+#include "prince/resource.h"
+#include "prince/animation.h"
+
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/archive.h"
+#include "common/memstream.h"
+
+namespace Prince {
+
+static const uint16 kNumOpcodes = 144;
+
+Room::Room() {}
+
+bool Room::loadRoom(byte *roomData) {
+ int roomSize = 64;
+ Common::MemoryReadStream roomStream(roomData, roomSize);
+
+ _mobs = roomStream.readSint32LE();
+ _backAnim = roomStream.readSint32LE();
+ _obj = roomStream.readSint32LE();
+ _nak = roomStream.readSint32LE();
+ _itemUse = roomStream.readSint32LE();
+ _itemGive = roomStream.readSint32LE();
+ _walkTo = roomStream.readSint32LE();
+ _examine = roomStream.readSint32LE();
+ _pickup = roomStream.readSint32LE();
+ _use = roomStream.readSint32LE();
+ _pushOpen = roomStream.readSint32LE();
+ _pullClose = roomStream.readSint32LE();
+ _talk = roomStream.readSint32LE();
+ _give = roomStream.readSint32LE();
+
+ return true;
+}
+
+int Room::getOptionOffset(int option) {
+ switch (option) {
+ case 0:
+ return _walkTo;
+ case 1:
+ return _examine;
+ case 2:
+ return _pickup;
+ case 3:
+ return _use;
+ case 4:
+ return _pushOpen;
+ case 5:
+ return _pullClose;
+ case 6:
+ return _talk;
+ case 7:
+ return _give;
+ default:
+ error("Wrong option - nr %d", option);
+ }
+}
+
+Script::Script(PrinceEngine *vm) : _vm(vm), _data(nullptr), _dataSize(0) {
+}
+
+Script::~Script() {
+ if (_data != nullptr) {
+ free(_data);
+ _dataSize = 0;
+ _data = nullptr;
+ }
+}
+
+bool Script::loadStream(Common::SeekableReadStream &stream) {
+ _dataSize = stream.size();
+ if (!_dataSize) {
+ return false;
+ }
+
+ _data = (byte *)malloc(_dataSize);
+
+ if (!_data) {
+ return false;
+ }
+
+ stream.read(_data, _dataSize);
+
+ Common::MemoryReadStream scriptDataStream(_data, _dataSize);
+ _scriptInfo.rooms = scriptDataStream.readSint32LE();
+ _scriptInfo.startGame = scriptDataStream.readSint32LE();
+ _scriptInfo.restoreGame = scriptDataStream.readSint32LE();
+ _scriptInfo.stdExamine = scriptDataStream.readSint32LE();
+ _scriptInfo.stdPickup = scriptDataStream.readSint32LE();
+ _scriptInfo.stdUse = scriptDataStream.readSint32LE();
+ _scriptInfo.stdOpen = scriptDataStream.readSint32LE();
+ _scriptInfo.stdClose = scriptDataStream.readSint32LE();
+ _scriptInfo.stdTalk = scriptDataStream.readSint32LE();
+ _scriptInfo.stdGive = scriptDataStream.readSint32LE();
+ _scriptInfo.usdCode = scriptDataStream.readSint32LE();
+ _scriptInfo.invObjExam = scriptDataStream.readSint32LE();
+ _scriptInfo.invObjUse = scriptDataStream.readSint32LE();
+ _scriptInfo.invObjUU = scriptDataStream.readSint32LE();
+ _scriptInfo.stdUseItem = scriptDataStream.readSint32LE();
+ _scriptInfo.lightSources = scriptDataStream.readSint32LE();
+ _scriptInfo.specRout = scriptDataStream.readSint32LE();
+ _scriptInfo.invObjGive = scriptDataStream.readSint32LE();
+ _scriptInfo.stdGiveItem = scriptDataStream.readSint32LE();
+ _scriptInfo.goTester = scriptDataStream.readSint32LE();
+
+ return true;
+}
+
+uint16 Script::readScript16(uint32 address) {
+ assert((_data + address + sizeof(uint16)) <= (_data + _dataSize));
+ uint16 data = READ_LE_UINT16(&_data[address]);
+ return data;
+}
+
+uint32 Script::readScript32(uint32 address) {
+ assert((_data + address + sizeof(uint32)) <= (_data + _dataSize));
+ uint32 data = READ_LE_UINT32(&_data[address]);
+ return data;
+}
+
+int16 Script::getLightX(int locationNr) {
+ return (int)READ_LE_UINT16(&_data[_scriptInfo.lightSources + locationNr * 8]);
+}
+
+int16 Script::getLightY(int locationNr) {
+ return (int)READ_LE_UINT16(&_data[_scriptInfo.lightSources + locationNr * 8 + 2]);
+}
+
+int32 Script::getShadowScale(int locationNr) {
+ return (int)READ_LE_UINT16(&_data[_scriptInfo.lightSources + locationNr * 8 + 4]);
+}
+
+uint32 Script::getStartGameOffset() {
+ return _scriptInfo.startGame;
+}
+
+uint32 Script::getLocationInitScript(int initRoomTableOffset, int roomNr) {
+ return (uint32)READ_LE_UINT32(&_data[initRoomTableOffset + roomNr * 4]);
+}
+
+byte Script::getMobVisible(int roomMobOffset, uint16 mob) {
+ return _data[roomMobOffset + mob];
+}
+
+void Script::setMobVisible(int roomMobOffset, uint16 mob, byte value) {
+ _data[roomMobOffset + mob] = value;
+}
+
+uint8 *Script::getRoomOffset(int locationNr) {
+ return &_data[_scriptInfo.rooms + locationNr * 64];
+}
+
+int32 Script::getOptionStandardOffset(int option) {
+ switch (option) {
+ case 1:
+ return _scriptInfo.stdExamine;
+ case 2:
+ return _scriptInfo.stdPickup;
+ case 3:
+ return _scriptInfo.stdUse;
+ case 4:
+ return _scriptInfo.stdOpen;
+ case 5:
+ return _scriptInfo.stdClose;
+ case 6:
+ return _scriptInfo.stdTalk;
+ case 7:
+ return _scriptInfo.stdGive;
+ default:
+ error("Wrong standard option - nr %d", option);
+ }
+}
+
+uint8 *Script::getHeroAnimName(int offset) {
+ return &_data[offset];
+}
+
+uint32 Script::getBackAnimId(int roomBackAnimOffset, int slot) {
+ uint32 animId = READ_LE_UINT32(&_data[roomBackAnimOffset + slot * 4]);
+ return animId;
+}
+
+void Script::setBackAnimId(int roomBackAnimOffset, int slot, int animId) {
+ WRITE_LE_UINT32(&_data[roomBackAnimOffset + slot * 4], animId);
+}
+
+byte Script::getObjId(int roomObjOffset, int slot) {
+ return _data[roomObjOffset + slot];
+}
+
+void Script::setObjId(int roomObjOffset, int slot, byte objectId) {
+ _data[roomObjOffset + slot] = objectId;
+}
+
+int Script::scanMobEvents(int mobMask, int dataEventOffset) {
+ debug("mobMask: %d", mobMask);
+ int i = 0;
+ int16 mob;
+ int32 code;
+ do {
+ mob = (int)READ_LE_UINT16(&_data[dataEventOffset + i * 6]);
+ if (mob == mobMask) {
+ code = (int)READ_LE_UINT32(&_data[dataEventOffset + i * 6 + 2]);
+ debug("code: %d", code);
+ return code;
+ }
+ i++;
+ } while (mob != -1);
+ return -1;
+}
+
+int Script::scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask) {
+ debug("mobMask: %d", mobMask);
+ int i = 0;
+ int16 mob;
+ int16 item;
+ int32 code;
+ do {
+ mob = (int)READ_LE_UINT16(&_data[dataEventOffset + i * 8]);
+ if (mob == mobMask) {
+ item = (int)READ_LE_UINT16(&_data[dataEventOffset + i * 8 + 2]);
+ if (item == itemMask) {
+ code = (int)READ_LE_UINT32(&_data[dataEventOffset + i * 8 + 4]);
+ debug("itemMask: %d", item);
+ debug("code: %d", code);
+ return code;
+ }
+ }
+ i++;
+ } while (mob != -1);
+ return -1;
+}
+
+void Script::installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset) {
+
+ _vm->removeSingleBackAnim(slot); // free slot before loading
+
+ int offset = roomBackAnimOffset + slot * 4; // BackgroundAnim offset for selected slot number
+
+ BackgroundAnim newBackgroundAnim; // BackgroundAnim seq data and its array of Anim
+
+ int animOffset = READ_LE_UINT32(&_data[offset]); // pos of BackgroundAnim data in script
+ int anims = READ_LE_UINT32(&_data[animOffset + 8]); // amount of Anim in BackgroundAnim
+
+ if (anims == 0) {
+ anims = 1; // anims with 0 as amount in game data has just 1 animation
+ }
+
+ if (animOffset != 0) {
+ Common::MemoryReadStream stream(_data, _dataSize); // stream from script data
+ for (int i = 0; i < anims; i++) {
+ Anim newAnim;
+ stream.seek(animOffset + kStructSizeBAS + kStructSizeBASA * i);
+ // Anim BASA data
+ newAnim._basaData._num = stream.readUint16LE();
+ newAnim._basaData._start = stream.readUint16LE();
+ newAnim._basaData._end = stream.readUint16LE();
+
+ // Anim number in game files
+ int animNumber = newAnim._basaData._num;
+ const Common::String animName = Common::String::format("AN%02d", animNumber);
+ const Common::String shadowName = Common::String::format("AN%02dS", animNumber);
+ newAnim._animData = new Animation();
+ newAnim._shadowData = new Animation();
+ Resource::loadResource(newAnim._animData, animName.c_str(), true);
+ if (!Resource::loadResource(newAnim._shadowData, shadowName.c_str(), false)) {
+ delete newAnim._shadowData;
+ newAnim._shadowData = nullptr;
+ }
+
+ newAnim._usage = 0;
+ newAnim._state = 0; // enabled
+ if ((_vm->_animList[animNumber]._flags & 4)) {
+ newAnim._state = 1;
+ newAnim._frame = _vm->_animList[animNumber]._endPhase;
+ newAnim._showFrame = _vm->_animList[animNumber]._endPhase;
+ } else {
+ newAnim._frame = _vm->_animList[animNumber]._startPhase;
+ newAnim._showFrame = _vm->_animList[animNumber]._startPhase;
+ }
+ newAnim._flags = _vm->_animList[animNumber]._flags;
+ newAnim._lastFrame = _vm->_animList[animNumber]._endPhase;
+ newAnim._loopFrame = _vm->_animList[animNumber]._loopPhase;
+ newAnim._loopType = _vm->_animList[animNumber]._loopType;
+ newAnim._nextAnim = _vm->_animList[animNumber]._nextAnim;
+ newAnim._x = _vm->_animList[animNumber]._x;
+ newAnim._y = _vm->_animList[animNumber]._y;
+ newAnim._currFrame = 0;
+ newAnim._currX = _vm->_animList[animNumber]._x;
+ newAnim._currY = _vm->_animList[animNumber]._y;
+ newAnim._currW = 0;
+ newAnim._currH = 0;
+ newAnim._packFlag = 0;
+ newAnim._shadowBack = _vm->_animList[animNumber]._type;
+ newBackgroundAnim.backAnims.push_back(newAnim);
+ }
+
+ // Anim BAS data
+ stream.seek(animOffset);
+ newBackgroundAnim._seq._type = stream.readUint32LE();
+ newBackgroundAnim._seq._data = stream.readUint32LE();
+ newBackgroundAnim._seq._anims = stream.readUint32LE();
+ stream.skip(12);
+ newBackgroundAnim._seq._current = newBackgroundAnim.backAnims[0]._basaData._num;
+ newBackgroundAnim._seq._counter = 0;
+ newBackgroundAnim._seq._currRelative = 0;
+ newBackgroundAnim._seq._data2 = stream.readUint32LE();
+
+ int start = newBackgroundAnim.backAnims[0]._basaData._start; // BASA_Start of first frame
+ int end = newBackgroundAnim.backAnims[0]._basaData._end; // BASA_End of first frame
+
+ if (start != -1) {
+ newBackgroundAnim.backAnims[0]._frame = start;
+ newBackgroundAnim.backAnims[0]._showFrame = start;
+ newBackgroundAnim.backAnims[0]._loopFrame = start;
+ }
+
+ if (end != -1) {
+ newBackgroundAnim.backAnims[0]._lastFrame = end;
+ }
+
+ backAnimList[slot] = newBackgroundAnim;
+ }
+}
+
+void Script::installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset) {
+ for (int i = 0; i < _vm->kMaxBackAnims; i++) {
+ installSingleBackAnim(backAnimList, i, roomBackAnimOffset);
+ }
+}
+
+void Script::installObjects(int offset) {
+ for (int i = 0; i < _vm->kMaxObjects; i++) {
+ _vm->_objSlot[i] = _data[offset];
+ offset++;
+ }
+}
+
+bool Script::loadAllMasks(Common::Array<Mask> &maskList, int offset) {
+ Mask tempMask;
+ while (1) {
+ Common::MemoryReadStream maskStream(_data, _dataSize);
+ maskStream.seek(offset);
+ tempMask._state = maskStream.readUint16LE();
+ if (tempMask._state == 0xffff) {
+ break;
+ }
+ tempMask._flags = maskStream.readUint16LE();
+ tempMask._x1 = maskStream.readUint16LE();
+ tempMask._y1 = maskStream.readUint16LE();
+ tempMask._x2 = maskStream.readUint16LE();
+ tempMask._y2 = maskStream.readUint16LE();
+ tempMask._z = maskStream.readUint16LE();
+ tempMask._number = maskStream.readUint16LE();
+
+ const Common::String msStreamName = Common::String::format("MS%02d", tempMask._number);
+ Common::SeekableReadStream *msStream = SearchMan.createReadStreamForMember(msStreamName);
+ if (!msStream) {
+ tempMask._width = 0;
+ tempMask._height = 0;
+ tempMask._data = nullptr;
+ debug("Can't load %s", msStreamName.c_str());
+ delete msStream;
+ } else {
+ int32 dataSize = msStream->size();
+ if (dataSize != -1) {
+ tempMask._data = (byte *)malloc(dataSize);
+ if (msStream->read(tempMask._data, dataSize) != (uint32)dataSize) {
+ free(tempMask._data);
+ delete msStream;
+ return false;
+ }
+ delete msStream;
+ }
+ tempMask._width = tempMask.getWidth();
+ tempMask._height = tempMask.getHeight();
+ }
+
+ maskList.push_back(tempMask);
+ offset += 16; // size of Mask (Nak) struct
+ }
+ return true;
+}
+
+InterpreterFlags::InterpreterFlags() {
+ resetAllFlags();
+}
+
+void InterpreterFlags::resetAllFlags() {
+ memset(_flags, 0, sizeof(_flags));
+}
+
+void InterpreterFlags::setFlagValue(Flags::Id flagId, int32 value) {
+ _flags[(uint32)flagId - kFlagMask] = value;
+}
+
+int32 InterpreterFlags::getFlagValue(Flags::Id flagId) {
+ return _flags[(uint32)flagId - kFlagMask];
+}
+
+Interpreter::Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags) :
+ _vm(vm), _script(script), _flags(flags),
+ _stacktop(0), _opcodeNF(false), _opcodeEnd(false),
+ _waitFlag(0), _result(true) {
+
+ // Initialize the script
+ _mode = "fg";
+ _fgOpcodePC = _script->getStartGameOffset();
+ _bgOpcodePC = 0;
+}
+
+void Interpreter::debugInterpreter(const char *s, ...) {
+ char buf[STRINGBUFLEN];
+ va_list va;
+ va_start(va, s);
+ vsnprintf(buf, STRINGBUFLEN, s, va);
+ va_end(va);
+
+ Common::String str = Common::String::format("@0x%08X: ", _lastInstruction);
+ str += Common::String::format("op %04d: ", _lastOpcode);
+ //debugC(10, DebugChannel::kScript, "PrinceEngine::Script %s %s", str.c_str(), buf);
+ if (!strcmp(_mode, "fg")) {
+ debug(10, "PrinceEngine::Script %s %s", str.c_str(), buf);
+ }
+ //debug("Prince::Script mode %s %s %s", _mode, str.c_str(), buf);
+}
+
+void Interpreter::stepBg() {
+ if (_bgOpcodePC) {
+ _mode = "bg";
+ _bgOpcodePC = step(_bgOpcodePC);
+ }
+}
+
+void Interpreter::stepFg() {
+ if (_fgOpcodePC) {
+ _mode = "fg";
+ _fgOpcodePC = step(_fgOpcodePC);
+ }
+}
+
+uint32 Interpreter::step(uint32 opcodePC) {
+ _currentInstruction = opcodePC;
+
+ while (!_opcodeNF) {
+ _lastInstruction = _currentInstruction;
+
+ // Get the current opcode
+ _lastOpcode = readScript16();
+
+ if (_lastOpcode >= kNumOpcodes)
+ error(
+ "Trying to execute unknown opcode @0x%04X: %02d",
+ _currentInstruction,
+ _lastOpcode);
+
+ // Execute the current opcode
+ OpcodeFunc op = _opcodes[_lastOpcode];
+ (this->*op)();
+ if (_opcodeNF) {
+ _opcodeNF = 0;
+ break;
+ }
+ }
+
+ if (_opcodeEnd) {
+ _vm->quitGame();
+ }
+
+ return _currentInstruction;
+}
+
+void Interpreter::storeNewPC(int opcodePC) {
+ if (_flags->getFlagValue(Flags::GETACTION) == 1) {
+ _flags->setFlagValue(Flags::GETACTIONDATA, opcodePC);
+ opcodePC = _flags->getFlagValue(Flags::GETACTIONBACK);
+ }
+ _fgOpcodePC = opcodePC;
+}
+
+int Interpreter::getLastOPCode() {
+ return _lastOpcode;
+}
+
+int Interpreter::getFgOpcodePC() {
+ return _fgOpcodePC;
+}
+
+uint32 Interpreter::getCurrentString() {
+ return _currentString;
+}
+
+void Interpreter::setCurrentString(uint32 value) {
+ _currentString = value;
+}
+
+byte *Interpreter::getString() {
+ return _string;
+}
+
+void Interpreter::setString(byte *newString) {
+ _string = newString;
+}
+
+void Interpreter::increaseString() {
+ while (*_string) {
+ _string++;
+ }
+ _string++;
+}
+
+void Interpreter::setResult(byte value) {
+ _result = value;
+}
+
+void Interpreter::setBgOpcodePC(uint32 value) {
+ _bgOpcodePC = value;
+}
+
+void Interpreter::setFgOpcodePC(uint32 value) {
+ _fgOpcodePC = value;
+}
+
+uint16 Interpreter::readScript16() {
+ uint16 data = _script->readScript16(_currentInstruction);
+ _currentInstruction += sizeof(uint16);
+ return data;
+}
+
+uint32 Interpreter::readScript32() {
+ uint32 data = _script->readScript32(_currentInstruction);
+ _currentInstruction += sizeof(uint32);
+ return data;
+}
+
+int32 Interpreter::readScriptFlagValue() {
+ uint16 value = readScript16();
+ if (value & InterpreterFlags::kFlagMask) {
+ return _flags->getFlagValue((Flags::Id)value);
+ }
+ return value;
+}
+
+Flags::Id Interpreter::readScriptFlagId() {
+ return (Flags::Id)readScript16();
+}
+
+void Interpreter::O_WAITFOREVER() {
+ _vm->changeCursor(_vm->_currentPointerNumber);
+ _opcodeNF = 1;
+ _currentInstruction -= 2;
+ //debugInterpreter("O_WAITFOREVER");
+}
+
+void Interpreter::O_BLACKPALETTE() {
+ _vm->blackPalette();
+ debugInterpreter("O_BLACKPALETTE");
+}
+
+void Interpreter::O_SETUPPALETTE() {
+ _vm->setPalette(_vm->_roomBmp->getPalette());
+ debugInterpreter("O_SETUPPALETTE");
+}
+
+void Interpreter::O_INITROOM() {
+ int32 roomId = readScriptFlagValue();
+ _vm->loadLocation(roomId);
+ _opcodeNF = 1;
+ debugInterpreter("O_INITROOM %d", roomId);
+}
+
+void Interpreter::O_SETSAMPLE() {
+ int32 sampleId = readScriptFlagValue();
+ int32 sampleNameOffset = readScript32();
+ const char *sampleName = _script->getString(_currentInstruction + sampleNameOffset - 4);
+ _vm->loadSample(sampleId, sampleName);
+ debugInterpreter("O_SETSAMPLE %d %s", sampleId, sampleName);
+}
+
+void Interpreter::O_FREESAMPLE() {
+ int32 sampleId = readScriptFlagValue();
+ _vm->freeSample(sampleId);
+ debugInterpreter("O_FREESAMPLE sampleId: %d", sampleId);
+}
+
+void Interpreter::O_PLAYSAMPLE() {
+ int32 sampleId = readScriptFlagValue();
+ uint16 loopType = readScript16();
+ _vm->playSample(sampleId, loopType);
+ debugInterpreter("O_PLAYSAMPLE sampleId %d loopType %d", sampleId, loopType);
+}
+
+void Interpreter::O_PUTOBJECT() {
+ int32 roomId = readScriptFlagValue();
+ int32 slot = readScriptFlagValue();
+ int32 objectId = readScriptFlagValue();
+ Room *room = new Room();
+ room->loadRoom(_script->getRoomOffset(roomId));
+ _vm->_script->setObjId(room->_obj, slot, objectId);
+ if (_vm->_locationNr == roomId) {
+ _vm->_objSlot[slot] = objectId;
+ }
+ delete room;
+ debugInterpreter("O_PUTOBJECT roomId %d, slot %d, objectId %d", roomId, slot, objectId);
+}
+
+void Interpreter::O_REMOBJECT() {
+ int32 roomId = readScriptFlagValue();
+ int32 slot = readScriptFlagValue();
+ Room *room = new Room();
+ room->loadRoom(_script->getRoomOffset(roomId));
+ _vm->_script->setObjId(room->_obj, slot, 0xFF);
+ if (_vm->_locationNr == roomId) {
+ _vm->_objSlot[slot] = 0xFF;
+ }
+ delete room;
+ debugInterpreter("O_REMOBJECT roomId %d slot %d", roomId, slot);
+}
+
+void Interpreter::O_SHOWANIM() {
+ int32 slot = readScriptFlagValue();
+ int32 animId = readScriptFlagValue();
+ _vm->freeNormAnim(slot);
+ Anim &anim = _vm->_normAnimList[slot];
+ AnimListItem &animList = _vm->_animList[animId];
+ anim._currFrame = 0;
+ anim._packFlag = 0;
+ anim._state = 0;
+ anim._frame = animList._startPhase;
+ anim._showFrame = animList._startPhase;
+ anim._lastFrame = animList._endPhase;
+ anim._loopFrame = animList._loopPhase;
+ anim._x = animList._x;
+ anim._y = animList._y;
+ anim._loopType = animList._loopType;
+ anim._shadowBack = animList._type;
+ anim._flags = animList._flags;
+ anim._nextAnim = animList._nextAnim;
+ int fileNumber = animList._fileNumber;
+ const Common::String animName = Common::String::format("AN%02d", fileNumber);
+ const Common::String shadowName = Common::String::format("AN%02dS", fileNumber);
+ anim._animData = new Animation();
+ anim._shadowData = new Animation();
+ Resource::loadResource(anim._animData, animName.c_str(), true);
+ if (!Resource::loadResource(anim._shadowData, shadowName.c_str(), false)) {
+ delete anim._shadowData;
+ anim._shadowData = nullptr;
+ }
+
+ // WALKAROUND: fix for turning off bard's wife background animation
+ // in front of bard's house (location 7) after giving her poem (item 33)
+ // in script: GiveLetter (line 11082)
+ if (_currentInstruction == kGiveLetterScriptFix) {
+ _vm->_backAnimList[1].backAnims[0]._state = 1;
+ }
+
+ debugInterpreter("O_SHOWANIM slot %d, animId %d", slot, animId);
+}
+
+void Interpreter::O_CHECKANIMEND() {
+ int32 slot = readScriptFlagValue();
+ if (_vm->_normAnimList[slot]._frame != _vm->_normAnimList[slot]._lastFrame - 1) {
+ _currentInstruction -= 4;
+ _opcodeNF = 1;
+ }
+ debugInterpreter("O_CHECKANIMEND slot %d", slot);
+}
+
+void Interpreter::O_FREEANIM() {
+ int32 slot = readScriptFlagValue();
+ _vm->freeNormAnim(slot);
+ debugInterpreter("O_FREEANIM slot %d", slot);
+}
+
+void Interpreter::O_CHECKANIMFRAME() {
+ int32 slot = readScriptFlagValue();
+ int32 frameNumber = readScriptFlagValue();
+ if (_vm->_normAnimList[slot]._frame != frameNumber - 1) {
+ _currentInstruction -= 6;
+ _opcodeNF = 1;
+ }
+ debugInterpreter("O_CHECKANIMFRAME slot %d, frameNumber %d", slot, frameNumber);
+}
+
+void Interpreter::O_PUTBACKANIM() {
+ int32 roomId = readScriptFlagValue();
+ int32 slot = readScriptFlagValue();
+ int32 animId = readScript32();
+ Room *room = new Room();
+ room->loadRoom(_script->getRoomOffset(roomId));
+ _vm->_script->setBackAnimId(room->_backAnim, slot, animId);
+ if (_vm->_locationNr == roomId) {
+ _vm->_script->installSingleBackAnim(_vm->_backAnimList, slot, room->_backAnim);
+ }
+ delete room;
+ debugInterpreter("O_PUTBACKANIM roomId %d, slot %d, animId %d", roomId, slot, animId);
+}
+
+void Interpreter::O_REMBACKANIM() {
+ int32 roomId = readScriptFlagValue();
+ int32 slot = readScriptFlagValue();
+ if (_vm->_locationNr == roomId) {
+ _vm->removeSingleBackAnim(slot);
+ }
+ Room *room = new Room();
+ room->loadRoom(_script->getRoomOffset(roomId));
+ _vm->_script->setBackAnimId(room->_backAnim, slot, 0);
+ delete room;
+ debugInterpreter("O_REMBACKANIM roomId %d, slot %d", roomId, slot);
+}
+
+void Interpreter::O_CHECKBACKANIMFRAME() {
+ int32 slotId = readScriptFlagValue();
+ int32 frameId = readScriptFlagValue();
+ int currAnim = _vm->_backAnimList[slotId]._seq._currRelative;
+ if (_vm->_backAnimList[slotId].backAnims[currAnim]._frame != frameId - 1) {
+ _currentInstruction -= 6;
+ _opcodeNF = 1;
+ }
+ debugInterpreter("O_CHECKBACKANIMFRAME slotId %d, frameId %d", slotId, frameId);
+}
+
+// Not used in script
+void Interpreter::O_FREEALLSAMPLES() {
+ error("O_FREEALLSAMPLES");
+}
+
+void Interpreter::O_SETMUSIC() {
+ uint16 musicId = readScript16();
+ _vm->loadMusic(musicId);
+ debugInterpreter("O_SETMUSIC musicId %d", musicId);
+}
+
+void Interpreter::O_STOPMUSIC() {
+ _vm->stopMusic();
+ debugInterpreter("O_STOPMUSIC");
+}
+
+void Interpreter::O__WAIT() {
+ int32 pause = readScriptFlagValue();
+ debugInterpreter("O__WAIT pause %d", pause);
+ if (!_waitFlag) {
+ // set new wait flag value and continue
+ _waitFlag = pause;
+ _opcodeNF = 1;
+ _currentInstruction -= 4;
+ return;
+ }
+ _waitFlag--;
+ if (_waitFlag > 0) {
+ _opcodeNF = 1;
+ _currentInstruction -= 4;
+ return;
+ }
+}
+
+// Not used in script
+void Interpreter::O_UPDATEOFF() {
+ error("O_UPDATEOFF");
+}
+
+// Not used in script
+void Interpreter::O_UPDATEON() {
+ error("O_UPDATEON");
+}
+
+// Not used in script
+void Interpreter::O_UPDATE () {
+ error("O_UPDATE");
+}
+
+// Not used in script
+void Interpreter::O_CLS() {
+ error("O_CLS");
+}
+
+void Interpreter::O__CALL() {
+ int32 address = readScript32();
+ _stack[_stacktop] = _currentInstruction;
+ _stacktop++;
+ _currentInstruction += address - 4;
+ debugInterpreter("O__CALL 0x%04X", _currentInstruction);
+}
+
+void Interpreter::O_RETURN() {
+ if (_stacktop > 0) {
+ _stacktop--;
+ _currentInstruction = _stack[_stacktop];
+ debugInterpreter("O_RETURN 0x%04X", _currentInstruction);
+ } else {
+ error("O_RETURN: Stack is empty");
+ }
+}
+
+void Interpreter::O_GO() {
+ int32 opPC = readScript32();
+ _currentInstruction += opPC - 4;
+ debugInterpreter("O_GO 0x%04X", opPC);
+}
+
+void Interpreter::O_BACKANIMUPDATEOFF() {
+ int32 slotId = readScriptFlagValue();
+ int currAnim = _vm->_backAnimList[slotId]._seq._currRelative;
+ if (!_vm->_backAnimList[slotId].backAnims.empty()) {
+ _vm->_backAnimList[slotId].backAnims[currAnim]._state = 1;
+ }
+ debugInterpreter("O_BACKANIMUPDATEOFF slotId %d", slotId);
+}
+
+void Interpreter::O_BACKANIMUPDATEON() {
+ int32 slotId = readScriptFlagValue();
+ int currAnim = _vm->_backAnimList[slotId]._seq._currRelative;
+ if (!_vm->_backAnimList[slotId].backAnims.empty()) {
+ _vm->_backAnimList[slotId].backAnims[currAnim]._state = 0;
+ }
+ debugInterpreter("O_BACKANIMUPDATEON slotId %d", slotId);
+}
+
+void Interpreter::O_CHANGECURSOR() {
+ int32 cursorId = readScriptFlagValue();
+ _vm->changeCursor(cursorId);
+ debugInterpreter("O_CHANGECURSOR %x", cursorId);
+}
+
+// Not used in script
+void Interpreter::O_CHANGEANIMTYPE() {
+ error("O_CHANGEANIMTYPE");
+}
+
+void Interpreter::O__SETFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _flags->setFlagValue((Flags::Id)(flagId), value);
+ debugInterpreter("O__SETFLAG 0x%04X (%s) = %d", flagId, Flags::getFlagName(flagId), value);
+}
+
+void Interpreter::O_COMPARE() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _result = _flags->getFlagValue(flagId) != value;
+ debugInterpreter("O_COMPARE flagId 0x%04X (%s), value %d == %d (%d)", flagId, Flags::getFlagName(flagId), value, _flags->getFlagValue(flagId), _result);
+}
+
+void Interpreter::O_JUMPZ() {
+ int32 offset = readScript32();
+ if (!_result) {
+ _currentInstruction += offset - 4;
+ }
+ debugInterpreter("O_JUMPZ result = %d, next %08x, offset 0x%08X", _result, _currentInstruction, offset);
+}
+
+void Interpreter::O_JUMPNZ() {
+ int32 offset = readScript32();
+ if (_result) {
+ _currentInstruction += offset - 4;
+ }
+ debugInterpreter("O_JUMPNZ result = %d, next %08x, offset 0x%08X", _result, _currentInstruction, offset);
+}
+
+void Interpreter::O_EXIT() {
+ int32 exitCode = readScriptFlagValue();
+ _opcodeEnd = true;
+ _opcodeNF = 1;
+ if (exitCode == 0x2EAD) {
+ _vm->scrollCredits();
+ }
+ debugInterpreter("O_EXIT exitCode %d", exitCode);
+}
+
+void Interpreter::O_ADDFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) + value);
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ }
+ else {
+ _result = 0;
+ }
+ debugInterpreter("O_ADDFLAG flagId %04x (%s), value %d", flagId, Flags::getFlagName(flagId), value);
+}
+
+void Interpreter::O_TALKANIM() {
+ int32 animNumber = readScriptFlagValue();
+ int32 slot = readScriptFlagValue();
+ _vm->doTalkAnim(animNumber, slot, kNormalAnimation);
+ debugInterpreter("O_TALKANIM animNumber %d, slot %d", animNumber, slot);
+}
+
+void Interpreter::O_SUBFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) - value);
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ }
+ else {
+ _result = 0;
+ }
+ debugInterpreter("O_SUBFLAG flagId %d, value %d", flagId, value);
+}
+
+void Interpreter::O_SETSTRING() {
+ int32 offset = readScript32();
+ _currentString = offset;
+ if (offset >= 80000) {
+ _string = _vm->_variaTxt->getString(offset - 80000);
+ debugInterpreter("GetVaria %s", _string);
+ }
+ else if (offset < 2000) {
+ _vm->_dialogData = &_vm->_dialogDat[offset * 4 - 4];
+ uint32 of = READ_LE_UINT32(_vm->_talkTxt + offset * 4);
+ const char *txt = (const char *)&_vm->_talkTxt[of];
+ _string = &_vm->_talkTxt[of];
+ debugInterpreter("TalkTxt %d %s", of, txt);
+ }
+ debugInterpreter("O_SETSTRING %04d", offset);
+}
+
+void Interpreter::O_ANDFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) & value);
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ } else {
+ _result = 0;
+ }
+ debugInterpreter("O_ANDFLAG flagId %d, value %d", flagId, value);
+}
+
+void Interpreter::O_GETMOBDATA() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 mobId = readScriptFlagValue();
+ int32 mobOffset = readScriptFlagValue();
+ int16 value = _vm->_mobList[mobId].getData((Mob::AttrId)mobOffset);
+ _flags->setFlagValue(flagId, value);
+ debugInterpreter("O_GETMOBDATA flagId %d, modId %d, mobOffset %d", flagId, mobId, mobOffset);
+}
+
+void Interpreter::O_ORFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) | value);
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ } else {
+ _result = 0;
+ }
+ debugInterpreter("O_ORFLAG flagId %d, value %d", flagId, value);
+}
+
+void Interpreter::O_SETMOBDATA() {
+ int32 mobId = readScriptFlagValue();
+ int32 mobOffset = readScriptFlagValue();
+ int32 value = readScriptFlagValue();
+ _vm->_mobList[mobId].setData((Mob::AttrId)mobOffset, value);
+ debugInterpreter("O_SETMOBDATA mobId %d, mobOffset %d, value %d", mobId, mobOffset, value);
+}
+
+void Interpreter::O_XORFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ _flags->setFlagValue(flagId, _flags->getFlagValue(flagId) ^ value);
+ if (_flags->getFlagValue(flagId)) {
+ _result = 1;
+ } else {
+ _result = 0;
+ }
+ debugInterpreter("O_XORFLAG flagId %d, value %d", flagId, value);
+}
+
+void Interpreter::O_GETMOBTEXT() {
+ int32 mob = readScriptFlagValue();
+ _currentString = _vm->_locationNr * 100 + mob + 60001;
+ _string = (byte *)_vm->_mobList[mob]._examText.c_str();
+ debugInterpreter("O_GETMOBTEXT mob %d", mob);
+}
+
+void Interpreter::O_MOVEHERO() {
+ int32 heroId = readScriptFlagValue();
+ int32 x = readScriptFlagValue();
+ int32 y = readScriptFlagValue();
+ int32 dir = readScriptFlagValue();
+ _vm->moveRunHero(heroId, x, y, dir, false);
+ debugInterpreter("O_MOVEHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir);
+}
+
+void Interpreter::O_WALKHERO() {
+ int32 heroId = readScriptFlagValue();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else if (heroId == 1) {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ if (hero->_state != Hero::kHeroStateStay) {
+ _currentInstruction -= 4;
+ _opcodeNF = 1;
+ }
+ }
+ debugInterpreter("O_WALKHERO %d", heroId);
+}
+
+void Interpreter::O_SETHERO() {
+ int32 heroId = readScriptFlagValue();
+ int32 x = readScriptFlagValue();
+ int32 y = readScriptFlagValue();
+ int32 dir = readScriptFlagValue();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else if (heroId == 1) {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ hero->setPos(x, y);
+ hero->_lastDirection = dir;
+ hero->_visible = 1;
+ hero->countDrawPosition();
+ }
+ debugInterpreter("O_SETHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir);
+}
+
+void Interpreter::O_HEROOFF() {
+ int32 heroId = readScriptFlagValue();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else if (heroId == 1) {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ hero->setVisible(false);
+ }
+ debugInterpreter("O_HEROOFF %d", heroId);
+}
+
+void Interpreter::O_HEROON() {
+ int32 heroId = readScriptFlagValue();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else if (heroId == 1) {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ hero->setVisible(true);
+ }
+ debugInterpreter("O_HEROON %d", heroId);
+}
+
+void Interpreter::O_CLSTEXT() {
+ int32 slot = readScriptFlagValue();
+ _vm->_textSlots[slot]._str = nullptr;
+ _vm->_textSlots[slot]._time = 0;
+ debugInterpreter("O_CLSTEXT slot %d", slot);
+}
+
+void Interpreter::O_CALLTABLE() {
+ Flags::Id flagId = readScriptFlagId();
+ int roomNr = _flags->getFlagValue(flagId);
+ int32 tableOffset = readScript32();
+ int initLocationScript = _script->getLocationInitScript(tableOffset, roomNr);
+ if (initLocationScript) {
+ _stack[_stacktop] = _currentInstruction;
+ _stacktop++;
+ _currentInstruction = initLocationScript;
+ }
+ debugInterpreter("O_CALLTABLE loc %d", roomNr);
+}
+
+void Interpreter::O_CHANGEMOB() {
+ int32 mob = readScriptFlagValue();
+ int32 value = readScriptFlagValue();
+ value ^= 1;
+ _vm->_script->setMobVisible(_vm->_room->_mobs, mob, value);
+ _vm->_mobList[mob]._visible = value;
+ debugInterpreter("O_CHANGEMOB mob %d, value %d", mob, value);
+}
+
+void Interpreter::O_ADDINV() {
+ int32 hero = readScriptFlagValue();
+ int32 item = readScriptFlagValue();
+ _vm->addInv(hero, item, false);
+ debugInterpreter("O_ADDINV hero %d, item %d", hero, item);
+}
+
+void Interpreter::O_REMINV() {
+ int32 hero = readScriptFlagValue();
+ int32 item = readScriptFlagValue();
+ _vm->remInv(hero, item);
+ debugInterpreter("O_REMINV hero %d, item %d", hero, item);
+}
+
+// Not used in script
+void Interpreter::O_REPINV() {
+ error("O_REPINV");
+}
+
+// Not used in script
+void Interpreter::O_OBSOLETE_GETACTION() {
+ error("O_OBSOLETE_GETACTION");
+}
+
+// Not used in script
+void Interpreter::O_ADDWALKAREA() {
+ error("O_ADDWALKAREA");
+}
+
+// Not used in script
+void Interpreter::O_REMWALKAREA() {
+ error("O_REMWALKAREA");
+}
+
+ // Not used in script
+void Interpreter::O_RESTOREWALKAREA() {
+ error("O_RESTOREWALKAREA");
+}
+
+void Interpreter::O_WAITFRAME() {
+ _opcodeNF = true;
+ debugInterpreter("O_WAITFRAME");
+}
+
+void Interpreter::O_SETFRAME() {
+ int32 anim = readScriptFlagValue();
+ int32 frame = readScriptFlagValue();
+ _vm->_normAnimList[anim]._frame = frame;
+ debugInterpreter("O_SETFRAME anim %d, frame %d", anim, frame);
+}
+
+// Not used in script
+void Interpreter::O_RUNACTION() {
+ error("O_RUNACTION");
+}
+
+void Interpreter::O_COMPAREHI() {
+ Flags::Id flag = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ int32 flagValue = _flags->getFlagValue(flag);
+ if (flagValue > value) {
+ _result = 0;
+ } else {
+ _result = 1;
+ }
+ debugInterpreter("O_COMPAREHI flag %04x - (%s), value %d, flagValue %d, result %d", flag, Flags::getFlagName(flag), value, flagValue, _result);
+}
+
+void Interpreter::O_COMPARELO() {
+ Flags::Id flag = readScriptFlagId();
+ int32 value = readScriptFlagValue();
+ int32 flagValue = _flags->getFlagValue(flag);
+ if (flagValue < value) {
+ _result = 0;
+ } else {
+ _result = 1;
+ }
+ debugInterpreter("O_COMPARELO flag %04x - (%s), value %d, flagValue %d, result %d", flag, Flags::getFlagName(flag), value, flagValue, _result);
+}
+
+// Not used in script
+void Interpreter::O_PRELOADSET() {
+ error("O_PRELOADSET");
+}
+
+// Not used in script
+void Interpreter::O_FREEPRELOAD() {
+ error("O_FREEPRELOAD");
+}
+
+// Not used in script
+void Interpreter::O_CHECKINV() {
+ error("O_CHECKINV");
+}
+
+void Interpreter::O_TALKHERO() {
+ int32 hero = readScriptFlagValue();
+ _vm->talkHero(hero);
+ debugInterpreter("O_TALKHERO hero %d", hero);
+}
+
+void Interpreter::O_WAITTEXT() {
+ int32 slot = readScriptFlagValue();
+ Text &text = _vm->_textSlots[slot];
+ if (text._time && text._str) {
+ if (_flags->getFlagValue(Flags::ESCAPED)) {
+ text._time = 1;
+ if (!slot) {
+ _vm->_mainHero->_talkTime = 1;
+ } else if (slot == 1) {
+ _vm->_secondHero->_talkTime = 1;
+ }
+ } else {
+ _opcodeNF = 1;
+ _currentInstruction -= 4;
+ }
+ }
+ //debugInterpreter("O_WAITTEXT slot %d", slot);
+}
+
+void Interpreter::O_SETHEROANIM() {
+ int32 heroId = readScriptFlagValue();
+ int32 offset = readScript32();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ hero->freeHeroAnim();
+ if (hero ->_specAnim == nullptr) {
+ hero->_specAnim = new Animation();
+ if (offset < 100) {
+ const Common::String animName = Common::String::format("AN%02d", offset);
+ Resource::loadResource(hero->_specAnim, animName.c_str(), true);
+ } else {
+ const Common::String animName = Common::String((const char *)_script->getHeroAnimName(offset));
+ Common::String normalizedPath = lastPathComponent(animName, '\\');
+ Resource::loadResource(hero->_specAnim, normalizedPath.c_str(), true);
+ }
+ hero->_phase = 0;
+ hero->_state = Hero::kHeroStateSpec;
+ }
+ }
+ debugInterpreter("O_SETHEROANIM hero %d, offset %d", hero, offset);
+}
+
+void Interpreter::O_WAITHEROANIM() {
+ int32 heroId = readScriptFlagValue();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ if (hero->_state == Hero::kHeroStateSpec) {
+ _currentInstruction -= 4;
+ _opcodeNF = 1;
+ }
+ }
+ debugInterpreter("O_WAITHEROANIM heroId %d", heroId);
+}
+
+void Interpreter::O_GETHERODATA() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 heroId = readScriptFlagValue();
+ int32 heroOffset = readScriptFlagValue();
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _vm->_mainHero;
+ } else {
+ hero = _vm->_secondHero;
+ }
+ if (hero != nullptr) {
+ _flags->setFlagValue(flagId, hero->getData((Hero::AttrId)heroOffset));
+ }
+ debugInterpreter("O_GETHERODATA flag %04x - (%s), heroId %d, heroOffset %d", flagId, Flags::getFlagName(flagId), heroId, heroOffset);
+}
+
+// No need of implementation here
+void Interpreter::O_GETMOUSEBUTTON() {
+ debugInterpreter("O_GETMOUSEBUTTON");
+}
+
+void Interpreter::O_CHANGEFRAMES() {
+ int32 anim = readScriptFlagValue();
+ int32 frame = readScriptFlagValue();
+ int32 lastFrame = readScriptFlagValue();
+ int32 loopFrame = readScriptFlagValue();
+ _vm->_normAnimList[anim]._frame = frame;
+ _vm->_normAnimList[anim]._lastFrame = lastFrame;
+ _vm->_normAnimList[anim]._loopFrame = loopFrame;
+ debugInterpreter("O_CHANGFRAMES anim %d, frame %d, lastFrame %d, loopFrame %d", anim, frame, lastFrame, loopFrame);
+}
+
+void Interpreter::O_CHANGEBACKFRAMES() {
+ int32 anim = readScriptFlagValue();
+ int32 frame = readScriptFlagValue();
+ int32 lastFrame = readScriptFlagValue();
+ int32 loopFrame = readScriptFlagValue();
+ int currAnim = _vm->_backAnimList[anim]._seq._currRelative;
+ Anim &backAnim = _vm->_backAnimList[anim].backAnims[currAnim];
+ backAnim._frame = frame;
+ backAnim._lastFrame = lastFrame;
+ backAnim._loopFrame = loopFrame;
+ debugInterpreter("O_CHANGEBACKFRAMES anim %d, frame %d, lastFrame %d, loopFrame %d", anim, frame, lastFrame, loopFrame);
+}
+
+void Interpreter::O_GETBACKANIMDATA() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 animNumber = readScriptFlagValue();
+ int32 animDataOffset = readScriptFlagValue();
+ int currAnim = _vm->_backAnimList[animNumber]._seq._currRelative;
+ int16 value = _vm->_backAnimList[animNumber].backAnims[currAnim].getAnimData((Anim::AnimOffsets)(animDataOffset));
+ _flags->setFlagValue((Flags::Id)(flagId), value);
+ debugInterpreter("O_GETBACKANIMDATA flag %04X (%s), animNumber %d, animDataOffset %d, value %d", flagId, Flags::getFlagName(flagId), animNumber, animDataOffset, value);
+}
+
+void Interpreter::O_GETANIMDATA() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 anim = readScriptFlagValue();
+ int32 animOffset = readScriptFlagValue();
+ if (_vm->_normAnimList[anim]._animData != nullptr) {
+ _flags->setFlagValue(flagId, _vm->_normAnimList[anim].getAnimData((Anim::AnimOffsets)(animOffset)));
+ }
+ debugInterpreter("O_GETANIMDATA flag %04X (%s), anim %d, animOffset %d", flagId, Flags::getFlagName(flagId), anim, animOffset);
+}
+
+void Interpreter::O_SETBGCODE() {
+ int32 offset = readScript32();
+ _bgOpcodePC = _currentInstruction + offset - 4;
+ debugInterpreter("O_SETBGCODE next %08x, offset %08x", _bgOpcodePC, offset);
+}
+
+void Interpreter::O_SETBACKFRAME() {
+ int32 anim = readScriptFlagValue();
+ int32 frame = readScriptFlagValue();
+ int currAnim = _vm->_backAnimList[anim]._seq._currRelative;
+ if (_vm->_backAnimList[anim].backAnims[currAnim]._animData != nullptr) {
+ _vm->_backAnimList[anim].backAnims[currAnim]._frame = frame;
+ }
+ debugInterpreter("O_SETBACKFRAME anim %d, frame %d", anim, frame);
+}
+
+void Interpreter::O_GETRND() {
+ Flags::Id flag = readScriptFlagId();
+ uint16 rndSeed = readScript16();
+ int value = _vm->_randomSource.getRandomNumber(rndSeed - 1);
+ _flags->setFlagValue(flag, value);
+ debugInterpreter("O_GETRND flag %d, rndSeed %d, value %d", flag, rndSeed, value);
+}
+
+void Interpreter::O_TALKBACKANIM() {
+ int32 animNumber = readScriptFlagValue();
+ int32 slot = readScriptFlagValue();
+ _vm->doTalkAnim(animNumber, slot, kBackgroundAnimation);
+ debugInterpreter("O_TALKBACKANIM animNumber %d, slot %d", animNumber, slot);
+}
+
+// Simplifying, because used only once in Location 20
+void Interpreter::O_LOADPATH() {
+ readScript32();
+ _vm->loadPath("path2");
+ debugInterpreter("O_LOADPATH - path2");
+}
+
+void Interpreter::O_GETCHAR() {
+ Flags::Id flagId = readScriptFlagId();
+ _flags->setFlagValue(flagId, *_string);
+ _string++;
+ debugInterpreter("O_GETCHAR %04X (%s) %02x", flagId, Flags::getFlagName(flagId), _flags->getFlagValue(flagId));
+}
+
+void Interpreter::O_SETDFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 address = readScript32();
+ _flags->setFlagValue((Flags::Id)(flagId), _currentInstruction + address - 4);
+ debugInterpreter("O_SETDFLAG 0x%04X (%s) = 0x%04X", flagId, Flags::getFlagName(flagId), _currentInstruction + address - 4);
+}
+
+void Interpreter::O_CALLDFLAG() {
+ Flags::Id flagId = readScriptFlagId();
+ _stack[_stacktop] = _currentInstruction;
+ _stacktop++;
+ _currentInstruction = _flags->getFlagValue(flagId);
+ debugInterpreter("O_CALLDFLAG 0x%04X (%s) = 0x%04X", flagId, Flags::getFlagName(flagId), _currentInstruction);
+}
+
+void Interpreter::O_PRINTAT() {
+ int32 slot = readScriptFlagValue();
+ int32 x = readScriptFlagValue();
+ int32 y = readScriptFlagValue();
+ int32 color = _flags->getFlagValue(Flags::KOLOR);
+ _vm->printAt(slot, color, (char *)_string, x, y);
+ increaseString();
+ debugInterpreter("O_PRINTAT slot %d, x %d, y %d", slot, x, y);
+}
+
+void Interpreter::O_ZOOMIN() {
+ int32 slot = readScriptFlagValue();
+ _vm->initZoomIn(slot);
+ debugInterpreter("O_ZOOMIN slot %04d", slot);
+}
+
+void Interpreter::O_ZOOMOUT() {
+ int32 slot = readScriptFlagValue();
+ _vm->initZoomOut(slot);
+ debugInterpreter("O_ZOOMOUT slot %d", slot);
+}
+
+// Not used in script
+void Interpreter::O_SETSTRINGOFFSET() {
+ error("O_SETSTRINGOFFSET");
+}
+
+void Interpreter::O_GETOBJDATA() {
+ Flags::Id flag = readScriptFlagId();
+ int32 slot = readScriptFlagValue();
+ int32 objOffset = readScriptFlagValue();
+ int nr = _vm->_objSlot[slot];
+ if (nr != 0xFF) {
+ int16 value = _vm->_objList[nr]->getData((Object::AttrId)objOffset);
+ _flags->setFlagValue(flag, value);
+ }
+ debugInterpreter("O_GETOBJDATA flag %d, objSlot %d, objOffset %d", flag, slot, objOffset);
+}
+
+void Interpreter::O_SETOBJDATA() {
+ int32 slot = readScriptFlagValue();
+ int32 objOffset = readScriptFlagValue();
+ int32 value = readScriptFlagValue();
+ int nr = _vm->_objSlot[slot];
+ if (nr != 0xFF) {
+ _vm->_objList[nr]->setData((Object::AttrId)objOffset, value);
+ }
+ debugInterpreter("O_SETOBJDATA objSlot %d, objOffset %d, value %d", slot, objOffset, value);
+}
+
+// Not used in script
+void Interpreter::O_SWAPOBJECTS() {
+ error("O_SWAPOBJECTS");
+}
+
+void Interpreter::O_CHANGEHEROSET() {
+ int32 heroId = readScriptFlagValue();
+ int32 heroSet = readScriptFlagValue();
+ if (!heroId) {
+ _vm->_mainHero->loadAnimSet(heroSet);
+ } else if (heroId == 1) {
+ _vm->_secondHero->loadAnimSet(heroSet);
+ }
+ debugInterpreter("O_CHANGEHEROSET hero %d, heroSet %d", heroId, heroSet);
+}
+
+// Not used in script
+void Interpreter::O_ADDSTRING() {
+ error("O_ADDSTRING");
+}
+
+void Interpreter::O_SUBSTRING() {
+ int32 value = readScriptFlagValue();
+ _string -= value;
+ debugInterpreter("O_SUBSTRING value %d", value);
+}
+
+int Interpreter::checkSeq(byte *string) {
+ int freeHSlotIncrease = 0;
+ byte c;
+ while ((c = string[0]) != 0xFF) {
+ string++;
+ if (c < 0xF0) {
+ freeHSlotIncrease++;
+ while ((c = string[0])) {
+ string++;
+ }
+ string++;
+ } else if (c != 0xFE) {
+ string++;
+ }
+ }
+ return freeHSlotIncrease;
+}
+
+void Interpreter::O_INITDIALOG() {
+ if (_string[0] == 255) {
+ byte *stringCurrOff = _string;
+ byte *string = _string;
+ stringCurrOff++;
+ int32 adressOfFirstSequence = (int)READ_LE_UINT16(stringCurrOff);
+ stringCurrOff += 2;
+ _string = string + adressOfFirstSequence;
+
+ for (int i = 0; i < 32; i++) {
+ _vm->_dialogBoxAddr[i] = 0;
+ _vm->_dialogOptAddr[i] = 0;
+ }
+
+ for (int i = 0; i < 4 * 32; i++) {
+ _vm->_dialogOptLines[i] = 0;
+ }
+
+ int16 off;
+ byte *line = nullptr;
+
+ int dialogBox = 0;
+ while ((off = (int)READ_LE_UINT16(stringCurrOff)) != -1) {
+ stringCurrOff += 2;
+ if (off) {
+ line = string + off;
+ }
+ _vm->_dialogBoxAddr[dialogBox] = line;
+ dialogBox++;
+ }
+ stringCurrOff += 2;
+
+ int dialogOpt = 0;
+ while ((off = (int)READ_LE_UINT16(stringCurrOff)) != -1) {
+ stringCurrOff += 2;
+ if (off) {
+ line = string + off;
+ }
+ _vm->_dialogOptAddr[dialogOpt] = line;
+ dialogOpt++;
+ }
+
+ _flags->setFlagValue(Flags::VOICE_A_LINE, 0);
+ _flags->setFlagValue(Flags::VOICE_B_LINE, 0); // bx in original?
+
+ int freeHSlot = 0;
+ for (int i = 31; i >= 0; i--) {
+ if (_vm->_dialogOptAddr[i] != 0) {
+ i++;
+ freeHSlot = i;
+ _flags->setFlagValue(Flags::VOICE_H_LINE, i);
+ break;
+ }
+ }
+
+ freeHSlot += checkSeq(_string);
+
+ for (int i = 0; i < 32; i++) {
+ _vm->_dialogOptLines[i * 4] = freeHSlot;
+ _vm->_dialogOptLines[i * 4 + 1] = freeHSlot;
+ _vm->_dialogOptLines[i * 4 + 2] = freeHSlot;
+ if (_vm->_dialogOptAddr[i]) {
+ freeHSlot += checkSeq(_vm->_dialogOptAddr[i]);
+ }
+ }
+ }
+ debugInterpreter("O_INITDIALOG");
+}
+
+void Interpreter::O_ENABLEDIALOGOPT() {
+ int32 opt = readScriptFlagValue();
+ int dialogDataValue = (int)READ_LE_UINT32(_vm->_dialogData);
+ dialogDataValue &= ~(1u << opt);
+ WRITE_LE_UINT32(_vm->_dialogData, dialogDataValue);
+ debugInterpreter("O_ENABLEDIALOGOPT opt %d", opt);
+}
+
+void Interpreter::O_DISABLEDIALOGOPT() {
+ int32 opt = readScriptFlagValue();
+ int dialogDataValue = (int)READ_LE_UINT32(_vm->_dialogData);
+ dialogDataValue |= (1u << opt);
+ WRITE_LE_UINT32(_vm->_dialogData, dialogDataValue);
+ debugInterpreter("O_DISABLEDIALOGOPT opt %d", opt);
+}
+
+void Interpreter::O_SHOWDIALOGBOX() {
+ int32 box = readScriptFlagValue();
+ uint32 currInstr = _currentInstruction;
+ _vm->createDialogBox(box);
+ _flags->setFlagValue(Flags::DIALINES, _vm->_dialogLines);
+ if (_vm->_dialogLines) {
+ _vm->changeCursor(1);
+ _vm->dialogRun();
+ _vm->changeCursor(0);
+ }
+ _currentInstruction = currInstr;
+ debugInterpreter("O_SHOWDIALOGBOX box %d", box);
+}
+
+void Interpreter::O_STOPSAMPLE() {
+ int32 slot = readScriptFlagValue();
+ _vm->stopSample(slot);
+ debugInterpreter("O_STOPSAMPLE slot %d", slot);
+}
+
+void Interpreter::O_BACKANIMRANGE() {
+ int32 slotId = readScriptFlagValue();
+ uint16 animId = readScript16();
+ int32 low = readScriptFlagValue();
+ int32 high = readScriptFlagValue();
+ if (animId != 0xFFFF) {
+ if (animId & InterpreterFlags::kFlagMask) {
+ animId = _flags->getFlagValue((Flags::Id)animId);
+ }
+ }
+ _result = 1;
+ if (!_vm->_backAnimList[slotId].backAnims.empty()) {
+ int currAnim = _vm->_backAnimList[slotId]._seq._currRelative;
+ if (_vm->_backAnimList[slotId].backAnims[currAnim]._animData != nullptr) {
+ if (animId == 0xFFFF || _vm->_backAnimList[slotId]._seq._current == animId) {
+ Anim &backAnim = _vm->_backAnimList[slotId].backAnims[currAnim];
+ if (!backAnim._state) {
+ if (backAnim._frame >= low) {
+ if (backAnim._frame <= high) {
+ _result = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ debugInterpreter("O_BACKANIMRANGE slotId %d, animId %d, low %d, high %d, _result %d", slotId, animId, low, high, _result);
+}
+
+void Interpreter::O_CLEARPATH() {
+ for (int i = 0; i < _vm->kPathBitmapLen; i++) {
+ _vm->_roomPathBitmap[i] = 255;
+ }
+ debugInterpreter("O_CLEARPATH");
+}
+
+void Interpreter::O_SETPATH() {
+ _vm->loadPath("path");
+ debugInterpreter("O_SETPATH");
+}
+
+void Interpreter::O_GETHEROX() {
+ int32 heroId = readScriptFlagValue();
+ Flags::Id flagId = readScriptFlagId();
+ if (!heroId) {
+ _flags->setFlagValue(flagId, _vm->_mainHero->_middleX);
+ } else if (heroId == 1) {
+ _flags->setFlagValue(flagId, _vm->_secondHero->_middleX);
+ }
+ debugInterpreter("O_GETHEROX heroId %d, flagId %d", heroId, flagId);
+}
+
+void Interpreter::O_GETHEROY() {
+ int32 heroId = readScriptFlagValue();
+ Flags::Id flagId = readScriptFlagId();
+ if (!heroId) {
+ _flags->setFlagValue(flagId, _vm->_mainHero->_middleY);
+ } else if (heroId == 1) {
+ _flags->setFlagValue(flagId, _vm->_secondHero->_middleY);
+ }
+ debugInterpreter("O_GETHEROY heroId %d, flagId %d", heroId, flagId);
+}
+
+void Interpreter::O_GETHEROD() {
+ int32 heroId = readScriptFlagValue();
+ Flags::Id flagId = readScriptFlagId();
+ if (!heroId) {
+ _flags->setFlagValue(flagId, _vm->_mainHero->_lastDirection);
+ } else if (heroId == 1) {
+ _flags->setFlagValue(flagId, _vm->_secondHero->_lastDirection);
+ }
+ debugInterpreter("O_GETHEROD heroId %d, flagId %d", heroId, flagId);
+}
+
+void Interpreter::O_PUSHSTRING() {
+ _stringStack.string = _string;
+ _stringStack.dialogData = _vm->_dialogData;
+ _stringStack.currentString = _currentString;
+ debugInterpreter("O_PUSHSTRING");
+}
+
+void Interpreter::O_POPSTRING() {
+ _string = _stringStack.string;
+ _vm->_dialogData = _stringStack.dialogData;
+ _currentString = _stringStack.currentString;
+ debugInterpreter("O_POPSTRING");
+}
+
+void Interpreter::O_SETFGCODE() {
+ int32 offset = readScript32();
+ _fgOpcodePC = _currentInstruction + offset - 4;
+ debugInterpreter("O_SETFGCODE next %08x, offset %08x", _fgOpcodePC, offset);
+}
+
+void Interpreter::O_STOPHERO() {
+ int32 heroId = readScriptFlagValue();
+ if (!heroId) {
+ _vm->_mainHero->freeOldMove();
+ } else if (heroId == 1) {
+ _vm->_secondHero->freeOldMove();
+ }
+ debugInterpreter("O_STOPHERO heroId %d", heroId);
+}
+
+void Interpreter::O_ANIMUPDATEOFF() {
+ int32 slotId = readScriptFlagValue();
+ _vm->_normAnimList[slotId]._state = 1;
+ debugInterpreter("O_ANIMUPDATEOFF slotId %d", slotId);
+}
+
+void Interpreter::O_ANIMUPDATEON() {
+ int32 slotId = readScriptFlagValue();
+ _vm->_normAnimList[slotId]._state = 0;
+ debugInterpreter("O_ANIMUPDATEON slotId %d", slotId);
+}
+
+void Interpreter::O_FREECURSOR() {
+ _vm->changeCursor(0);
+ _vm->_currentPointerNumber = 1;
+ // free memory here?
+ debugInterpreter("O_FREECURSOR");
+}
+
+void Interpreter::O_ADDINVQUIET() {
+ int32 hero = readScriptFlagValue();
+ int32 item = readScriptFlagValue();
+ _vm->addInv(hero, item, true);
+ debugInterpreter("O_ADDINVQUIET hero %d, item %d", hero, item);
+}
+
+void Interpreter::O_RUNHERO() {
+ int32 heroId = readScriptFlagValue();
+ int32 x = readScriptFlagValue();
+ int32 y = readScriptFlagValue();
+ int32 dir = readScriptFlagValue();
+ _vm->moveRunHero(heroId, x, y, dir, true);
+ debugInterpreter("O_RUNHERO heroId %d, x %d, y %d, dir %d", heroId, x, y, dir);
+}
+
+void Interpreter::O_SETBACKANIMDATA() {
+ uint16 animNumber = readScript16();
+ uint16 animDataOffset = readScript16();
+ Flags::Id flagId = readScriptFlagId();
+ uint16 value = _flags->getFlagValue((Flags::Id)(flagId));
+ int currAnim = _vm->_backAnimList[animNumber]._seq._currRelative;
+ _vm->_backAnimList[animNumber].backAnims[currAnim].setAnimData((Anim::AnimOffsets)(animDataOffset), value);
+ debugInterpreter("O_SETBACKANIMDATA flag %04X (%s), animNumber %d, animDataOffset %d, value %d", flagId, Flags::getFlagName(flagId), animNumber, animDataOffset, value);
+}
+
+void Interpreter::O_VIEWFLC() {
+ int32 animNr = readScriptFlagValue();
+ _vm->_flcFrameSurface = nullptr;
+ _vm->loadAnim(animNr, false);
+ debugInterpreter("O_VIEWFLC animNr %d", animNr);
+}
+
+void Interpreter::O_CHECKFLCFRAME() {
+ int32 frameNr = readScriptFlagValue();
+ debugInterpreter("O_CHECKFLCFRAME frame number %d", frameNr);
+ if (_vm->_flicPlayer.getCurFrame() != frameNr) {
+ _currentInstruction -= 4;
+ _opcodeNF = 1;
+ }
+}
+
+void Interpreter::O_CHECKFLCEND() {
+ const Video::FlicDecoder &flicPlayer = _vm->_flicPlayer;
+ debugInterpreter("O_CHECKFLCEND frameCount %d, currentFrame %d", flicPlayer.getFrameCount(), flicPlayer.getCurFrame());
+ if (flicPlayer.getFrameCount() - flicPlayer.getCurFrame() > 1) {
+ _currentInstruction -= 2;
+ _opcodeNF = 1;
+ }
+}
+
+void Interpreter::O_FREEFLC() {
+ _vm->_flcFrameSurface = nullptr;
+ debugInterpreter("O_FREEFLC");
+}
+
+void Interpreter::O_TALKHEROSTOP() {
+ int32 heroId = readScriptFlagValue();
+ if (!heroId) {
+ _vm->_mainHero->_state = Hero::kHeroStateStay;
+ } else if (heroId == 1) {
+ _vm->_secondHero->_state = Hero::kHeroStateStay;
+ }
+ debugInterpreter("O_TALKHEROSTOP %d", heroId);
+}
+
+void Interpreter::O_HEROCOLOR() {
+ int32 heroId = readScriptFlagValue();
+ int32 color = readScriptFlagValue();
+ if (!heroId) {
+ _vm->_mainHero->_color = color;
+ } else if (heroId == 1) {
+ _vm->_secondHero->_color = color;
+ }
+ debugInterpreter("O_HEROCOLOR heroId %d, color %d", heroId, color);
+}
+
+void Interpreter::O_GRABMAPA() {
+ _vm->grabMap();
+ debugInterpreter("O_GRABMAPA");
+}
+
+void Interpreter::O_ENABLENAK() {
+ int32 nakId = readScriptFlagValue();
+ _vm->_maskList[nakId]._flags = 0;
+ debugInterpreter("O_ENABLENAK nakId %d", nakId);
+}
+
+void Interpreter::O_DISABLENAK() {
+ int32 nakId = readScriptFlagValue();
+ _vm->_maskList[nakId]._flags = 1;
+ debugInterpreter("O_DISABLENAK nakId %d", nakId);
+}
+
+void Interpreter::O_GETMOBNAME() {
+ int32 modId = readScriptFlagValue();
+ _string = (byte *)_vm->_mobList[modId]._name.c_str();
+ debugInterpreter("O_GETMOBNAME modId %d", modId);
+}
+
+void Interpreter::O_SWAPINVENTORY() {
+ int32 hero = readScriptFlagValue();
+ _vm->swapInv(hero);
+ debugInterpreter("O_SWAPINVENTORY hero %d", hero);
+}
+
+void Interpreter::O_CLEARINVENTORY() {
+ int32 hero = readScriptFlagValue();
+ _vm->clearInv(hero);
+ debugInterpreter("O_CLEARINVENTORY hero %d", hero);
+}
+
+void Interpreter::O_SKIPTEXT() {
+ increaseString();
+ debugInterpreter("O_SKIPTEXT");
+}
+
+void Interpreter::O_SETVOICEH() {
+ int32 slot = readScriptFlagValue();
+ static const uint32 VOICE_H_SLOT = 28;
+ uint16 voiceLineH = _flags->getFlagValue(Flags::VOICE_H_LINE);
+ _vm->setVoice(slot, VOICE_H_SLOT, voiceLineH);
+}
+
+void Interpreter::O_SETVOICEA() {
+ int32 slot = readScriptFlagValue();
+ static const uint32 VOICE_A_SLOT = 29;
+ uint16 voiceLineH = _flags->getFlagValue(Flags::VOICE_H_LINE);
+ _vm->setVoice(slot, VOICE_A_SLOT, voiceLineH);
+}
+
+void Interpreter::O_SETVOICEB() {
+ int32 slot = readScriptFlagValue();
+ static const uint32 VOICE_B_SLOT = 30;
+ uint16 voiceLineH = _flags->getFlagValue(Flags::VOICE_H_LINE);
+ _vm->setVoice(slot, VOICE_B_SLOT, voiceLineH);
+}
+
+void Interpreter::O_SETVOICEC() {
+ int32 slot = readScriptFlagValue();
+ static const uint32 VOICE_C_SLOT = 31;
+ uint16 voiceLineH = _flags->getFlagValue(Flags::VOICE_H_LINE);
+ _vm->setVoice(slot, VOICE_C_SLOT, voiceLineH);
+}
+
+void Interpreter::O_SETVOICED() {
+ int32 slot = readScriptFlagValue();
+ static const uint32 VOICE_D_SLOT = 32;
+ uint16 voiceLineH = _flags->getFlagValue(Flags::VOICE_H_LINE);
+ _vm->setVoice(slot, VOICE_D_SLOT, voiceLineH);
+}
+
+void Interpreter::O_VIEWFLCLOOP() {
+ int32 animId = readScriptFlagValue();
+ _vm->loadAnim(animId, true);
+ debugInterpreter("O_VIEWFLCLOOP animId %d", animId);
+}
+
+// Not used in script
+void Interpreter::O_FLCSPEED() {
+ int32 speed = readScriptFlagValue();
+ error("O_FLCSPEED speed %d", speed);
+}
+
+void Interpreter::O_OPENINVENTORY() {
+ _vm->_showInventoryFlag = true;
+ _opcodeNF = 1;
+ debugInterpreter("O_OPENINVENTORY");
+}
+
+void Interpreter::O_KRZYWA() {
+ _vm->makeCurve();
+ debugInterpreter("O_KRZYWA");
+}
+
+void Interpreter::O_GETKRZYWA() {
+ _vm->getCurve();
+ debugInterpreter("O_GETKRZYWA");
+}
+
+void Interpreter::O_GETMOB() {
+ Flags::Id flagId = readScriptFlagId();
+ int32 posX = readScriptFlagValue();
+ int32 posY = readScriptFlagValue();
+ int mobNumber = _vm->getMob(_vm->_mobList, true, posX, posY);
+ _flags->setFlagValue(flagId, mobNumber + 1);
+ debugInterpreter("O_GETMOB flagId %d, posX %d, posY %d", flagId, posX, posY);
+}
+
+// Not used in game
+void Interpreter::O_INPUTLINE() {
+ error("O_INPUTLINE");
+}
+
+// Not used in script
+void Interpreter::O_BREAK_POINT() {
+ error("O_BREAK_POINT");
+}
+
+Interpreter::OpcodeFunc Interpreter::_opcodes[kNumOpcodes] = {
+ &Interpreter::O_WAITFOREVER,
+ &Interpreter::O_BLACKPALETTE,
+ &Interpreter::O_SETUPPALETTE,
+ &Interpreter::O_INITROOM,
+ &Interpreter::O_SETSAMPLE,
+ &Interpreter::O_FREESAMPLE,
+ &Interpreter::O_PLAYSAMPLE,
+ &Interpreter::O_PUTOBJECT,
+ &Interpreter::O_REMOBJECT,
+ &Interpreter::O_SHOWANIM,
+ &Interpreter::O_CHECKANIMEND,
+ &Interpreter::O_FREEANIM,
+ &Interpreter::O_CHECKANIMFRAME,
+ &Interpreter::O_PUTBACKANIM,
+ &Interpreter::O_REMBACKANIM,
+ &Interpreter::O_CHECKBACKANIMFRAME,
+ &Interpreter::O_FREEALLSAMPLES,
+ &Interpreter::O_SETMUSIC,
+ &Interpreter::O_STOPMUSIC,
+ &Interpreter::O__WAIT,
+ &Interpreter::O_UPDATEOFF,
+ &Interpreter::O_UPDATEON,
+ &Interpreter::O_UPDATE ,
+ &Interpreter::O_CLS,
+ &Interpreter::O__CALL,
+ &Interpreter::O_RETURN,
+ &Interpreter::O_GO,
+ &Interpreter::O_BACKANIMUPDATEOFF,
+ &Interpreter::O_BACKANIMUPDATEON,
+ &Interpreter::O_CHANGECURSOR,
+ &Interpreter::O_CHANGEANIMTYPE,
+ &Interpreter::O__SETFLAG,
+ &Interpreter::O_COMPARE,
+ &Interpreter::O_JUMPZ,
+ &Interpreter::O_JUMPNZ,
+ &Interpreter::O_EXIT,
+ &Interpreter::O_ADDFLAG,
+ &Interpreter::O_TALKANIM,
+ &Interpreter::O_SUBFLAG,
+ &Interpreter::O_SETSTRING,
+ &Interpreter::O_ANDFLAG,
+ &Interpreter::O_GETMOBDATA,
+ &Interpreter::O_ORFLAG,
+ &Interpreter::O_SETMOBDATA,
+ &Interpreter::O_XORFLAG,
+ &Interpreter::O_GETMOBTEXT,
+ &Interpreter::O_MOVEHERO,
+ &Interpreter::O_WALKHERO,
+ &Interpreter::O_SETHERO,
+ &Interpreter::O_HEROOFF,
+ &Interpreter::O_HEROON,
+ &Interpreter::O_CLSTEXT,
+ &Interpreter::O_CALLTABLE,
+ &Interpreter::O_CHANGEMOB,
+ &Interpreter::O_ADDINV,
+ &Interpreter::O_REMINV,
+ &Interpreter::O_REPINV,
+ &Interpreter::O_OBSOLETE_GETACTION,
+ &Interpreter::O_ADDWALKAREA,
+ &Interpreter::O_REMWALKAREA,
+ &Interpreter::O_RESTOREWALKAREA,
+ &Interpreter::O_WAITFRAME,
+ &Interpreter::O_SETFRAME,
+ &Interpreter::O_RUNACTION,
+ &Interpreter::O_COMPAREHI,
+ &Interpreter::O_COMPARELO,
+ &Interpreter::O_PRELOADSET,
+ &Interpreter::O_FREEPRELOAD,
+ &Interpreter::O_CHECKINV,
+ &Interpreter::O_TALKHERO,
+ &Interpreter::O_WAITTEXT,
+ &Interpreter::O_SETHEROANIM,
+ &Interpreter::O_WAITHEROANIM,
+ &Interpreter::O_GETHERODATA,
+ &Interpreter::O_GETMOUSEBUTTON,
+ &Interpreter::O_CHANGEFRAMES,
+ &Interpreter::O_CHANGEBACKFRAMES,
+ &Interpreter::O_GETBACKANIMDATA,
+ &Interpreter::O_GETANIMDATA,
+ &Interpreter::O_SETBGCODE,
+ &Interpreter::O_SETBACKFRAME,
+ &Interpreter::O_GETRND,
+ &Interpreter::O_TALKBACKANIM,
+ &Interpreter::O_LOADPATH,
+ &Interpreter::O_GETCHAR,
+ &Interpreter::O_SETDFLAG,
+ &Interpreter::O_CALLDFLAG,
+ &Interpreter::O_PRINTAT,
+ &Interpreter::O_ZOOMIN,
+ &Interpreter::O_ZOOMOUT,
+ &Interpreter::O_SETSTRINGOFFSET,
+ &Interpreter::O_GETOBJDATA,
+ &Interpreter::O_SETOBJDATA,
+ &Interpreter::O_SWAPOBJECTS,
+ &Interpreter::O_CHANGEHEROSET,
+ &Interpreter::O_ADDSTRING,
+ &Interpreter::O_SUBSTRING,
+ &Interpreter::O_INITDIALOG,
+ &Interpreter::O_ENABLEDIALOGOPT,
+ &Interpreter::O_DISABLEDIALOGOPT,
+ &Interpreter::O_SHOWDIALOGBOX,
+ &Interpreter::O_STOPSAMPLE,
+ &Interpreter::O_BACKANIMRANGE,
+ &Interpreter::O_CLEARPATH,
+ &Interpreter::O_SETPATH,
+ &Interpreter::O_GETHEROX,
+ &Interpreter::O_GETHEROY,
+ &Interpreter::O_GETHEROD,
+ &Interpreter::O_PUSHSTRING,
+ &Interpreter::O_POPSTRING,
+ &Interpreter::O_SETFGCODE,
+ &Interpreter::O_STOPHERO,
+ &Interpreter::O_ANIMUPDATEOFF,
+ &Interpreter::O_ANIMUPDATEON,
+ &Interpreter::O_FREECURSOR,
+ &Interpreter::O_ADDINVQUIET,
+ &Interpreter::O_RUNHERO,
+ &Interpreter::O_SETBACKANIMDATA,
+ &Interpreter::O_VIEWFLC,
+ &Interpreter::O_CHECKFLCFRAME,
+ &Interpreter::O_CHECKFLCEND,
+ &Interpreter::O_FREEFLC,
+ &Interpreter::O_TALKHEROSTOP,
+ &Interpreter::O_HEROCOLOR,
+ &Interpreter::O_GRABMAPA,
+ &Interpreter::O_ENABLENAK,
+ &Interpreter::O_DISABLENAK,
+ &Interpreter::O_GETMOBNAME,
+ &Interpreter::O_SWAPINVENTORY,
+ &Interpreter::O_CLEARINVENTORY,
+ &Interpreter::O_SKIPTEXT,
+ &Interpreter::O_SETVOICEH,
+ &Interpreter::O_SETVOICEA,
+ &Interpreter::O_SETVOICEB,
+ &Interpreter::O_SETVOICEC,
+ &Interpreter::O_VIEWFLCLOOP,
+ &Interpreter::O_FLCSPEED,
+ &Interpreter::O_OPENINVENTORY,
+ &Interpreter::O_KRZYWA,
+ &Interpreter::O_GETKRZYWA,
+ &Interpreter::O_GETMOB,
+ &Interpreter::O_INPUTLINE,
+ &Interpreter::O_SETVOICED,
+ &Interpreter::O_BREAK_POINT,
+};
+
+} // End of namespace Prince
diff --git a/engines/prince/script.h b/engines/prince/script.h
new file mode 100644
index 0000000000..4799e84944
--- /dev/null
+++ b/engines/prince/script.h
@@ -0,0 +1,397 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_SCRIPT_H
+#define PRINCE_SCRIPT_H
+
+#include "common/random.h"
+#include "common/endian.h"
+#include "common/array.h"
+#include "common/stream.h"
+
+#include "prince/flags.h"
+
+namespace Prince {
+
+class PrinceEngine;
+class Animation;
+class Object;
+struct Anim;
+struct BackgroundAnim;
+struct Mask;
+
+class Room {
+public:
+ Room();
+ int _mobs; // mob flag offset
+ int _backAnim; // offset to array of animation numbers
+ int _obj; // offset to array of object numbers
+ int _nak; // offset to array of masks
+ int _itemUse;
+ int _itemGive;
+ int _walkTo; // offset to array of WALKTO events or 0
+ int _examine; // offset to array of EXAMINE events or 0
+ int _pickup;
+ int _use;
+ int _pushOpen;
+ int _pullClose;
+ int _talk;
+ int _give;
+
+ bool loadStream(Common::SeekableReadStream &stream);
+ bool loadRoom(byte *roomData);
+ int getOptionOffset(int option);
+
+private:
+
+ typedef void (Room::*LoadingStep)(Common::SeekableReadStream &stream);
+
+ void nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step);
+
+ void loadMobs(Common::SeekableReadStream &stream);
+ void loadBackAnim(Common::SeekableReadStream &stream);
+ void loadObj(Common::SeekableReadStream &stream);
+ void loadNak(Common::SeekableReadStream &stream);
+ void loadItemUse(Common::SeekableReadStream &stream);
+ void loadItemGive(Common::SeekableReadStream &stream);
+ void loadWalkTo(Common::SeekableReadStream &stream);
+ void loadExamine(Common::SeekableReadStream &stream);
+ void loadPickup(Common::SeekableReadStream &stream);
+ void loadUse(Common::SeekableReadStream &stream);
+ void loadPushOpen(Common::SeekableReadStream &stream);
+ void loadPullClose(Common::SeekableReadStream &stream);
+ void loadTalk(Common::SeekableReadStream &stream);
+ void loadGive(Common::SeekableReadStream &stream);
+};
+
+
+class Script {
+public:
+ static const int16 kMaxRooms = 60;
+
+ Script(PrinceEngine *vm);
+ ~Script();
+
+ struct ScriptInfo {
+ int rooms;
+ int startGame;
+ int restoreGame;
+ int stdExamine;
+ int stdPickup;
+ int stdUse;
+ int stdOpen;
+ int stdClose;
+ int stdTalk;
+ int stdGive;
+ int usdCode;
+ int invObjExam;
+ int invObjUse;
+ int invObjUU;
+ int stdUseItem;
+ int lightSources;
+ int specRout;
+ int invObjGive;
+ int stdGiveItem;
+ int goTester;
+ };
+
+ ScriptInfo _scriptInfo;
+
+ bool loadStream(Common::SeekableReadStream &stream);
+
+ uint16 readScript16(uint32 address);
+ uint32 readScript32(uint32 address);
+
+ uint32 getStartGameOffset();
+ uint32 getLocationInitScript(int initRoomTableOffset, int roomNr);
+ int16 getLightX(int locationNr);
+ int16 getLightY(int locationNr);
+ int32 getShadowScale(int locationNr);
+ uint8 *getRoomOffset(int locationNr);
+ int32 getOptionStandardOffset(int option);
+ uint8 *getHeroAnimName(int offset);
+
+ void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset);
+ void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset);
+ void installObjects(int offset);
+ bool loadAllMasks(Common::Array<Mask> &maskList, int offset);
+
+ int scanMobEvents(int mobMask, int dataEventOffset);
+ int scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask);
+
+ byte getMobVisible(int roomMobOffset, uint16 mob);
+ void setMobVisible(int roomMobOffset, uint16 mob, byte value);
+
+ uint32 getBackAnimId(int roomBackAnimOffset, int slot);
+ void setBackAnimId(int roomBackAnimOffset, int slot, int animId);
+
+ byte getObjId(int roomObjOffset, int slot);
+ void setObjId(int roomObjOffset, int slot, byte objectId);
+
+ const char *getString(uint32 offset) {
+ return (const char *)(&_data[offset]);
+ }
+
+private:
+ PrinceEngine *_vm;
+ uint8 *_data;
+ uint32 _dataSize;
+ Common::Array<Room> _roomList;
+};
+
+class InterpreterFlags {
+public:
+ InterpreterFlags();
+
+ void setFlagValue(Flags::Id flag, int32 value);
+ int32 getFlagValue(Flags::Id flag);
+
+ void resetAllFlags();
+
+ static const uint16 kFlagMask = 0x8000;
+ static const uint16 kMaxFlags = 2000;
+private:
+ int32 _flags[kMaxFlags];
+};
+
+class Interpreter {
+public:
+ Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags);
+
+ void stopBg() { _bgOpcodePC = 0; }
+
+ void stepBg();
+ void stepFg();
+ void storeNewPC(int opcodePC);
+ int getLastOPCode();
+ int getFgOpcodePC();
+
+ void setBgOpcodePC(uint32 value);
+ void setFgOpcodePC(uint32 value);
+
+ uint32 getCurrentString();
+ void setCurrentString(uint32 value);
+
+ byte *getString();
+ void setString(byte *newString);
+ void increaseString();
+
+ void setResult(byte value);
+
+private:
+ PrinceEngine *_vm;
+ Script *_script;
+ InterpreterFlags *_flags;
+
+ uint32 _currentInstruction;
+
+ uint32 _bgOpcodePC;
+ uint32 _fgOpcodePC;
+
+ uint16 _lastOpcode;
+ uint32 _lastInstruction;
+ byte _result;
+
+ bool _opcodeNF; // break interpreter loop
+ bool _opcodeEnd; // end of a game flag
+
+ static const uint32 _STACK_SIZE = 500;
+ uint32 _stack[_STACK_SIZE];
+ struct stringStack {
+ byte *string;
+ byte *dialogData;
+ uint32 currentString;
+ } _stringStack;
+ uint8 _stacktop;
+ uint32 _waitFlag;
+
+ byte *_string;
+ uint32 _currentString;
+ const char *_mode;
+
+ // Helper functions
+ uint32 step(uint32 opcodePC);
+ uint16 readScript16();
+ uint32 readScript32();
+ int32 readScriptFlagValue();
+ Flags::Id readScriptFlagId();
+ int checkSeq(byte *string);
+
+ void debugInterpreter(const char *s, ...);
+
+ typedef void (Interpreter::*OpcodeFunc)();
+ static OpcodeFunc _opcodes[];
+
+ static const int kGiveLetterScriptFix = 79002;
+
+ // Keep opcode handlers names as they are in original code
+ // making it easier to switch back and forth
+ void O_WAITFOREVER();
+ void O_BLACKPALETTE();
+ void O_SETUPPALETTE();
+ void O_INITROOM();
+ void O_SETSAMPLE();
+ void O_FREESAMPLE();
+ void O_PLAYSAMPLE();
+ void O_PUTOBJECT();
+ void O_REMOBJECT();
+ void O_SHOWANIM();
+ void O_CHECKANIMEND();
+ void O_FREEANIM();
+ void O_CHECKANIMFRAME();
+ void O_PUTBACKANIM();
+ void O_REMBACKANIM();
+ void O_CHECKBACKANIMFRAME();
+ void O_FREEALLSAMPLES();
+ void O_SETMUSIC();
+ void O_STOPMUSIC();
+ void O__WAIT();
+ void O_UPDATEOFF();
+ void O_UPDATEON();
+ void O_UPDATE ();
+ void O_CLS();
+ void O__CALL();
+ void O_RETURN();
+ void O_GO();
+ void O_BACKANIMUPDATEOFF();
+ void O_BACKANIMUPDATEON();
+ void O_CHANGECURSOR();
+ void O_CHANGEANIMTYPE();
+ void O__SETFLAG();
+ void O_COMPARE();
+ void O_JUMPZ();
+ void O_JUMPNZ();
+ void O_EXIT();
+ void O_ADDFLAG();
+ void O_TALKANIM();
+ void O_SUBFLAG();
+ void O_SETSTRING();
+ void O_ANDFLAG();
+ void O_GETMOBDATA();
+ void O_ORFLAG();
+ void O_SETMOBDATA();
+ void O_XORFLAG();
+ void O_GETMOBTEXT();
+ void O_MOVEHERO();
+ void O_WALKHERO();
+ void O_SETHERO();
+ void O_HEROOFF();
+ void O_HEROON();
+ void O_CLSTEXT();
+ void O_CALLTABLE();
+ void O_CHANGEMOB();
+ void O_ADDINV();
+ void O_REMINV();
+ void O_REPINV();
+ void O_OBSOLETE_GETACTION();
+ void O_ADDWALKAREA();
+ void O_REMWALKAREA();
+ void O_RESTOREWALKAREA();
+ void O_WAITFRAME();
+ void O_SETFRAME();
+ void O_RUNACTION();
+ void O_COMPAREHI();
+ void O_COMPARELO();
+ void O_PRELOADSET();
+ void O_FREEPRELOAD();
+ void O_CHECKINV();
+ void O_TALKHERO();
+ void O_WAITTEXT();
+ void O_SETHEROANIM();
+ void O_WAITHEROANIM();
+ void O_GETHERODATA();
+ void O_GETMOUSEBUTTON();
+ void O_CHANGEFRAMES();
+ void O_CHANGEBACKFRAMES();
+ void O_GETBACKANIMDATA();
+ void O_GETANIMDATA();
+ void O_SETBGCODE();
+ void O_SETBACKFRAME();
+ void O_GETRND();
+ void O_TALKBACKANIM();
+ void O_LOADPATH();
+ void O_GETCHAR();
+ void O_SETDFLAG();
+ void O_CALLDFLAG();
+ void O_PRINTAT();
+ void O_ZOOMIN();
+ void O_ZOOMOUT();
+ void O_SETSTRINGOFFSET();
+ void O_GETOBJDATA();
+ void O_SETOBJDATA();
+ void O_SWAPOBJECTS();
+ void O_CHANGEHEROSET();
+ void O_ADDSTRING();
+ void O_SUBSTRING();
+ void O_INITDIALOG();
+ void O_ENABLEDIALOGOPT();
+ void O_DISABLEDIALOGOPT();
+ void O_SHOWDIALOGBOX();
+ void O_STOPSAMPLE();
+ void O_BACKANIMRANGE();
+ void O_CLEARPATH();
+ void O_SETPATH();
+ void O_GETHEROX();
+ void O_GETHEROY();
+ void O_GETHEROD();
+ void O_PUSHSTRING();
+ void O_POPSTRING();
+ void O_SETFGCODE();
+ void O_STOPHERO();
+ void O_ANIMUPDATEOFF();
+ void O_ANIMUPDATEON();
+ void O_FREECURSOR();
+ void O_ADDINVQUIET();
+ void O_RUNHERO();
+ void O_SETBACKANIMDATA();
+ void O_VIEWFLC();
+ void O_CHECKFLCFRAME();
+ void O_CHECKFLCEND();
+ void O_FREEFLC();
+ void O_TALKHEROSTOP();
+ void O_HEROCOLOR();
+ void O_GRABMAPA();
+ void O_ENABLENAK();
+ void O_DISABLENAK();
+ void O_GETMOBNAME();
+ void O_SWAPINVENTORY();
+ void O_CLEARINVENTORY();
+ void O_SKIPTEXT();
+ void O_SETVOICEH();
+ void O_SETVOICEA();
+ void O_SETVOICEB();
+ void O_SETVOICEC();
+ void O_VIEWFLCLOOP();
+ void O_FLCSPEED();
+ void O_OPENINVENTORY();
+ void O_KRZYWA();
+ void O_GETKRZYWA();
+ void O_GETMOB();
+ void O_INPUTLINE();
+ void O_SETVOICED();
+ void O_BREAK_POINT();
+
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/sound.cpp b/engines/prince/sound.cpp
new file mode 100644
index 0000000000..032297ee43
--- /dev/null
+++ b/engines/prince/sound.cpp
@@ -0,0 +1,211 @@
+/* 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 "prince/prince.h"
+#include "prince/sound.h"
+#include "prince/musNum.h"
+
+#include "common/config-manager.h"
+#include "common/memstream.h"
+#include "common/archive.h"
+#include "audio/decoders/raw.h"
+#include "audio/audiostream.h"
+
+namespace Prince {
+
+const char *MusicPlayer::_musTable[] = {
+ "",
+ "Battlfld.mid",
+ "Cave.mid",
+ "Cemetery.mid",
+ "Credits.mid",
+ "Fjord.mid",
+ "Guitar.mid",
+ "Hell.mid",
+ "Jingle.mid",
+ "Main.mid",
+ "Night.mid",
+ "Reality.mid",
+ "Sunlord.mid",
+ "Tavern.mid",
+ "Temple.mid",
+ "Boruta.mid",
+ "Intro.mid"
+};
+
+const uint8 MusicPlayer::_musRoomTable[] = {
+ 0,
+ ROOM01MUS,
+ ROOM02MUS,
+ ROOM03MUS,
+ ROOM04MUS,
+ ROOM05MUS,
+ ROOM06MUS,
+ ROOM07MUS,
+ ROOM08MUS,
+ ROOM09MUS,
+ ROOM10MUS,
+ ROOM11MUS,
+ ROOM12MUS,
+ ROOM13MUS,
+ ROOM14MUS,
+ ROOM15MUS,
+ ROOM16MUS,
+ ROOM17MUS,
+ ROOM18MUS,
+ ROOM19MUS,
+ ROOM20MUS,
+ ROOM21MUS,
+ ROOM22MUS,
+ ROOM23MUS,
+ ROOM24MUS,
+ ROOM25MUS,
+ ROOM26MUS,
+ ROOM27MUS,
+ ROOM28MUS,
+ ROOM29MUS,
+ ROOM30MUS,
+ ROOM31MUS,
+ ROOM32MUS,
+ ROOM33MUS,
+ ROOM34MUS,
+ ROOM35MUS,
+ ROOM36MUS,
+ ROOM37MUS,
+ ROOM38MUS,
+ ROOM39MUS,
+ ROOM40MUS,
+ ROOM41MUS,
+ ROOM42MUS,
+ ROOM43MUS,
+ 0,
+ 0,
+ ROOM46MUS,
+ ROOM47MUS,
+ ROOM48MUS,
+ ROOM49MUS,
+ ROOM50MUS,
+ ROOM51MUS,
+ ROOM52MUS,
+ ROOM53MUS,
+ ROOM54MUS,
+ ROOM55MUS,
+ ROOM56MUS,
+ ROOM57MUS,
+ ROOM58MUS,
+ ROOM59MUS,
+ ROOM60MUS,
+ ROOM61MUS
+};
+
+
+MusicPlayer::MusicPlayer(PrinceEngine *vm) : _vm(vm) {
+ _data = nullptr;
+ _isGM = false;
+
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+MusicPlayer::~MusicPlayer() {
+ killMidi();
+}
+
+void MusicPlayer::killMidi() {
+ Audio::MidiPlayer::stop();
+
+ free(_data);
+ _data = nullptr;
+}
+
+void MusicPlayer::loadMidi(const char *name) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
+ if (!stream) {
+ debug("Can't load midi stream %s", name);
+ return;
+ }
+
+ // Stop any currently playing MIDI file
+ killMidi();
+
+ // Read in the data for the file
+ _dataSize = stream->size();
+ _data = (byte *)malloc(_dataSize);
+ stream->read(_data, _dataSize);
+
+ delete stream;
+
+ // Start playing the music
+ sndMidiStart();
+}
+
+void MusicPlayer::sndMidiStart() {
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_data, _dataSize)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ syncVolume();
+
+ // Al the tracks are supposed to loop
+ _isLooping = true;
+ _isPlaying = true;
+ }
+}
+
+void MusicPlayer::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
+ }
+
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/sound.h b/engines/prince/sound.h
new file mode 100644
index 0000000000..cc44b0a110
--- /dev/null
+++ b/engines/prince/sound.h
@@ -0,0 +1,67 @@
+/* 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.
+ *
+ */
+
+#ifndef PRINCE_SOUND_H
+#define PRINCE_SOUND_H
+
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+#include "audio/fmopl.h"
+#include "audio/mididrv.h"
+#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
+#include "audio/mixer.h"
+#include "common/memstream.h"
+
+namespace Prince {
+
+class PrinceEngine;
+
+class MusicPlayer: public Audio::MidiPlayer {
+private:
+ PrinceEngine *_vm;
+ byte *_data;
+ int _dataSize;
+ bool _isGM;
+
+ // Start MIDI File
+ void sndMidiStart();
+
+ // Stop MIDI File
+ void sndMidiStop();
+public:
+ MusicPlayer(PrinceEngine *vm);
+ ~MusicPlayer();
+
+ void loadMidi(const char *);
+ void killMidi();
+
+ virtual void send(uint32 b);
+ virtual void sendToChannel(byte channel, uint32 b);
+
+ static const char *_musTable[];
+ static const uint8 _musRoomTable[];
+};
+
+} // End of namespace Prince
+
+#endif
diff --git a/engines/prince/variatxt.cpp b/engines/prince/variatxt.cpp
new file mode 100644
index 0000000000..c38c65ce5d
--- /dev/null
+++ b/engines/prince/variatxt.cpp
@@ -0,0 +1,55 @@
+/* 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 "prince/variatxt.h"
+#include "common/debug.h"
+
+namespace Prince {
+
+VariaTxt::VariaTxt() : _dataSize(0), _data(nullptr) {
+}
+
+VariaTxt::~VariaTxt() {
+ _dataSize = 0;
+ if (_data != nullptr) {
+ free(_data);
+ _data = nullptr;
+ }
+}
+
+
+bool VariaTxt::loadStream(Common::SeekableReadStream &stream) {
+ _dataSize = stream.size();
+ _data = (byte *)malloc(_dataSize);
+ stream.read(_data, _dataSize);
+ return true;
+}
+
+byte *VariaTxt::getString(uint32 stringId) {
+ uint32 stringOffset = READ_LE_UINT32(_data + stringId * 4);
+ if (stringOffset > _dataSize) {
+ assert(false);
+ }
+ return _data + stringOffset;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/variatxt.h b/engines/prince/variatxt.h
new file mode 100644
index 0000000000..04c34bc0ef
--- /dev/null
+++ b/engines/prince/variatxt.h
@@ -0,0 +1,40 @@
+/* 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 "common/stream.h"
+
+namespace Prince {
+
+class VariaTxt {
+public:
+ VariaTxt();
+ ~VariaTxt();
+
+ bool loadStream(Common::SeekableReadStream &stream);
+ byte *getString(uint32 stringId);
+
+private:
+ uint32 _dataSize;
+ byte *_data;
+};
+
+} // End of namespace Prince
diff --git a/engines/queen/POTFILES b/engines/queen/POTFILES
index 1baf9c24de..28624662ca 100644
--- a/engines/queen/POTFILES
+++ b/engines/queen/POTFILES
@@ -1 +1 @@
-engines/queen/queen.cpp
+engines/queen/detection.cpp
diff --git a/engines/queen/logic.cpp b/engines/queen/logic.cpp
index d48bb8a498..664a9a15f9 100644
--- a/engines/queen/logic.cpp
+++ b/engines/queen/logic.cpp
@@ -2115,9 +2115,15 @@ void LogicInterview::setupSpecialMoveTable() {
}
void LogicGame::useJournal() {
+ _vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
+
_vm->command()->clear(false);
_journal->use();
_vm->walk()->stopJoe();
+
+ _vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
}
bool LogicGame::changeToSpecialRoom() {
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp
index 1b9d72babc..e86a53d448 100644
--- a/engines/queen/talk.cpp
+++ b/engines/queen/talk.cpp
@@ -189,7 +189,7 @@ void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) {
}
}
- if (_vm->input()->talkQuit())
+ if (_vm->input()->talkQuit() || _vm->shouldQuit())
break;
retval = _dialogueTree[level][selectedSentence].dialogueNodeValue1;
@@ -1250,15 +1250,12 @@ int16 Talk::selectSentence() {
}
_vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
if (sentenceCount > 0) {
int oldZone = 0;
- while (0 == selectedSentence) {
-
- if (_vm->input()->talkQuit())
- break;
-
+ while (0 == selectedSentence && !_vm->input()->talkQuit() && !_vm->shouldQuit()) {
_vm->update();
Common::Point mouse = _vm->input()->getMousePos();
@@ -1328,6 +1325,9 @@ int16 Talk::selectSentence() {
}
}
+ _vm->input()->clearKeyVerb();
+ _vm->input()->clearMouseButton();
+
debug(6, "Selected sentence %i", selectedSentence);
arrowBobUp->active = false;
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index b8a5436d76..8dc27c74be 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -468,7 +468,6 @@ public:
int actorIdToIndex(uint16 id) { return (id == ID_PROTAG) ? 0 : objectIdToIndex(id); }
uint16 actorIndexToId(int index) { return (index == 0) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); }
ActorData *getActor(uint16 actorId);
- ActorData *getFirstActor() { return &_actors.front(); }
// clarification: Obj - means game object, such Hat, Spoon etc, Object - means Actor,Obj,HitZone,StepZone
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index 90ba62070b..e659e09ce8 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -215,8 +215,7 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
#ifdef ENABLE_IHNM
if (getGameId() == GID_IHNM) {
out->writeSint32LE(_scene->currentChapterNumber());
- // Protagonist
- out->writeSint32LE(_scene->currentProtag());
+ out->writeSint32LE(0); // obsolete, was used for the protagonist
out->writeSint32LE(_scene->getCurrentMusicTrack());
out->writeSint32LE(_scene->getCurrentMusicRepeat());
}
@@ -316,7 +315,7 @@ void SagaEngine::load(const char *fileName) {
if (getGameId() == GID_IHNM) {
int currentChapter = _scene->currentChapterNumber();
_scene->setChapterNumber(in->readSint32LE());
- _scene->setProtag(in->readSint32LE());
+ in->skip(4); // obsolete, was used for setting the protagonist
if (_scene->currentChapterNumber() != currentChapter)
_scene->changeScene(-2, 0, kTransitionFade, _scene->currentChapterNumber());
_scene->setCurrentMusicTrack(in->readSint32LE());
@@ -366,30 +365,6 @@ void SagaEngine::load(const char *fileName) {
int volume = _music->getVolume();
_music->setVolume(0);
-#ifdef ENABLE_IHNM
- // Protagonist swapping
- if (getGameId() == GID_IHNM) {
- if (_scene->currentProtag() != 0 && _scene->currentChapterNumber() != 6) {
- ActorData *actor1 = _actor->getFirstActor();
- ActorData *actor2;
- // The original gets actor2 from the current protagonist ID, but this is sometimes wrong
- // If the current protagonist ID is not correct, use the stored protagonist
- if (!_actor->validActorId(_scene->currentProtag())) {
- actor2 = _actor->_protagonist;
- } else {
- actor2 = _actor->getActor(_scene->currentProtag());
- }
-
- SWAP(actor1->_location, actor2->_location);
-
- actor2->_flags &= ~kProtagonist;
- actor1->_flags |= kProtagonist;
- _actor->_protagonist = _actor->_centerActor = actor1;
- _scene->setProtag(actor1->_id);
- }
- }
-#endif
-
_scene->clearSceneQueue();
_scene->changeScene(sceneNumber, ACTOR_NO_ENTRANCE, kTransitionNoFade);
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index 6a9571d282..410713c5d5 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -286,8 +286,6 @@ class Scene {
#endif
return _sceneLUT[sceneNumber];
}
- int currentProtag() const { return _currentProtag; }
- void setProtag(int pr) { _currentProtag = pr; }
int currentSceneNumber() const { return _sceneNumber; }
int currentChapterNumber() const { return _chapterNumber; }
void setChapterNumber(int ch) { _chapterNumber = ch; }
@@ -341,7 +339,6 @@ class Scene {
Common::Array<uint16> _sceneLUT;
SceneQueueList _sceneQueue;
bool _sceneLoaded;
- int _currentProtag;
int _sceneNumber;
int _chapterNumber;
int _outsetSceneNumber;
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index cb963e23ac..2175d8f40a 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -748,14 +748,10 @@ void Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
actor1->_flags &= ~kProtagonist;
actor2->_flags |= kProtagonist;
_vm->_actor->_protagonist = _vm->_actor->_centerActor = actor2;
- if (_vm->getGameId() == GID_IHNM)
- _vm->_scene->setProtag(actorId2);
} else if (actor2->_flags & kProtagonist) {
actor2->_flags &= ~kProtagonist;
actor1->_flags |= kProtagonist;
_vm->_actor->_protagonist = _vm->_actor->_centerActor = actor1;
- if (_vm->getGameId() == GID_IHNM)
- _vm->_scene->setProtag(actorId1);
}
}
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index edb12a3dd9..1e1c397212 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -438,7 +438,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < 64; ++i)
oldValues[curChannel][i] = 0;
- int arrayTerminator = MIN<int>(64, blockSize);
+ uint arrayTerminator = MIN<int>(64, blockSize);
for (i = 0; i < arrayTerminator; ++i)
oldValues[curChannel][i] = buffer[curChannel][blockSize - (i + 1)];
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 565e9752c3..510c8cd9ca 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -485,6 +485,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) {
#endif
debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]);
debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no");
+ debugPrintf("Uses 16 bit color matching: %s\n", g_sci->_gfxPalette->isUsing16bitColorMatch() ? "yes" : "no");
debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc());
debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc());
debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no");
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 4f28738508..85ff1c0062 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -563,31 +563,28 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
// If these files aren't found, it can't be SCI
- if (!foundResMap && !foundRes000) {
+ if (!foundResMap && !foundRes000)
return 0;
- }
ResourceManager resMan;
- resMan.addAppropriateSources(fslist);
- resMan.init(true);
+ resMan.addAppropriateSourcesForDetection(fslist);
+ resMan.initForDetection();
// TODO: Add error handling.
#ifndef ENABLE_SCI32
// Is SCI32 compiled in? If not, and this is a SCI32 game,
// stop here
- if (getSciVersion() >= SCI_VERSION_2) {
- return (const ADGameDescription *)&s_fallbackDesc;
- }
+ if (getSciVersionForDetection() >= SCI_VERSION_2)
+ return 0;
#endif
ViewType gameViews = resMan.getViewType();
// Have we identified the game views? If not, stop here
- // Can't be SCI (or unsupported SCI views). Pinball Creep by sierra also uses resource.map/resource.000 files
- // but doesnt share sci format at all, if we dont return 0 here we will detect this game as SCI
- if (gameViews == kViewUnknown) {
+ // Can't be SCI (or unsupported SCI views). Pinball Creep by Sierra also uses resource.map/resource.000 files
+ // but doesn't share SCI format at all
+ if (gameViews == kViewUnknown)
return 0;
- }
// Set the platform to Amiga if the game is using Amiga views
if (gameViews == kViewAmiga)
@@ -597,9 +594,8 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
Common::String sierraGameId = resMan.findSierraGameId();
// If we don't have a game id, the game is not SCI
- if (sierraGameId.empty()) {
+ if (sierraGameId.empty())
return 0;
- }
Common::String gameId = convertSierraGameId(sierraGameId, &s_fallbackDesc.flags, resMan);
strncpy(s_fallbackGameIdBuf, gameId.c_str(), sizeof(s_fallbackGameIdBuf) - 1);
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 91b3c45c6e..0fddaa51b4 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -1832,15 +1832,12 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
-#if 0
- // The resource.002 file, contained in disk 3, is broken in this version
- // (it contains a large chunk of zeroes and several broken resources,
- // e.g. pic 250 and views 250 and 251).
- // Thus this detection entry isn't accurate.
-
- // Larry 1 Remake - English Amiga (from www.back2roots.org)
+ // Larry 1 Remake - English Amiga
// Executable scanning reports "1.004.024"
// SCI interpreter version 1.000.784
+ // NOTE: The resource.002 file, contained in disk 3, is broken in the
+ // www.back2roots.org version (it contains a large chunk of zeroes and
+ // several broken resources, e.g. pic 250 and views 250 and 251).
{"lsl1sci", "SCI", {
{"resource.map", 0, "7d115a9e27dc8ac71e8d5ef33d589bd5", 3366},
{"resource.000", 0, "e67fd129d5810fc7ad8ea509d891cc00", 363073},
@@ -1849,7 +1846,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251},
AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
-#endif
// Larry 1 VGA Remake - English DOS (from spookypeanut)
// Executable scanning reports "1.000.577", VERSION file reports "2.1"
@@ -4119,6 +4115,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
FANMADE("Knight's Quest Demo 1.0", "5e816edf993956752ed06fccfeeae6d9", 1260, "959321f88a22905fa1f8c6d897874744", 703836),
FANMADE("LockerGnome Quest", "3eeff9130206cad0c4e1551e2b9dd2c5", 420, "ae05ca90806fd90cc43f147c82d3547c", 158906),
FANMADE("LockerGnome Quest Redux", "55b0081dbdd77a07807c76cec3606970", 492, "75c9c5e8a475a7b5f1a6cb18edad67f2", 168069),
+ FANMADE("LockerGnome Quest Redux", "6299578d8ab709cc181baea6b984a0a7", 492, "c0ff4bfcc62fb111337343967e4001fd", 167383),
FANMADE("New Year's Mystery", "e4dcab1b1d3cb4a2c070a07a9c9589e0", 708, "e00ca5e44fd4e98d8174b467b31b0f21", 295425),
FANMADE("New Year's Mystery (Updated)", "efd1beb5120293725065c95959144f81", 714, "b3bd3c2372ed6efa28adb12403c4c31a", 305027),
FANMADE("Ocean Battle", "c2304a0568e0eb84f8e9a0915f01170a", 408, "46c520c1ac9b63528854d0f58c7e1b74", 142234),
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 61fb717567..c56eb09482 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -37,6 +37,7 @@
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/savegame.h"
+#include "sci/graphics/menu.h"
#include "sci/sound/audio.h"
#include "sci/console.h"
@@ -913,6 +914,25 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
// code concerning this via script patch.
s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
break;
+ case GID_JONES:
+ // HACK: The code that enables certain menu items isn't called when a game is restored from the
+ // launcher, or the "Restore game" option in the game's main menu - bugs #6537 and #6723.
+ // These menu entries are disabled when the game is launched, and are enabled when a new game is
+ // started. The code for enabling these entries is is all in script 1, room1::init, but that code
+ // path is never followed in these two cases (restoring game from the menu, or restoring a game
+ // from the ScummVM launcher). Thus, we perform the calls to enable the menus ourselves here.
+ // These two are needed when restoring from the launcher
+ // FIXME: The original interpreter saves and restores the menu state, so these attributes
+ // are automatically reset there. We may want to do the same.
+ g_sci->_gfxMenu->kernelSetAttribute(257 >> 8, 257 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> About Jones
+ g_sci->_gfxMenu->kernelSetAttribute(258 >> 8, 258 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> Help
+ // The rest are normally enabled from room1::init
+ g_sci->_gfxMenu->kernelSetAttribute(769 >> 8, 769 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Options -> Delete current player
+ g_sci->_gfxMenu->kernelSetAttribute(513 >> 8, 513 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game
+ g_sci->_gfxMenu->kernelSetAttribute(515 >> 8, 515 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Restore Game
+ g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics
+ g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals
+ break;
default:
break;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index cdcdcc41e5..9decc4cef6 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -844,6 +844,8 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin
if (voc)
voc->saveLoadWithSerializer(ser);
+ // TODO: SSCI (at least JonesCD, presumably more) also stores the Menu state
+
return true;
}
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index 511d2014bd..b1c002413d 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -262,7 +262,7 @@ SciEvent EventManager::getScummVMEvent() {
// Scancodify if appropriate
if (modifiers & Common::KBD_ALT)
input.character = altify(input.character);
- else if ((modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
+ if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
input.character += 96; // 0x01 -> 'a'
// If no actual key was pressed (e.g. if only a modifier key was pressed),
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 91b5b25e99..fafc734895 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -784,13 +784,10 @@ void GfxFrameout::kernelFrameout() {
// swapped in the GK1 inventory screen, investigate why.
// This is also needed for GK1 rooms 710 and 720 (catacombs, inner and
// outer circle), for handling the tiles and talking to Wolfgang.
- // HACK: Fix the coordinates by explicitly setting them here.
- Common::Rect objNSRect = g_sci->_gfxCompare->getNSRect(itemEntry->object);
- uint16 roomNumber = g_sci->getEngineState()->currentRoomNumber();
- if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0 ||
- (g_sci->getGameId() == GID_GK1 && (roomNumber == 710 || roomNumber == 720))) {
+ // HACK: Fix the coordinates by explicitly setting them here for GK1.
+ // Also check bug #6729, for another case where this is needed.
+ if (g_sci->getGameId() == GID_GK1)
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
- }
}
// Don't attempt to draw sprites that are outside the visible
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index a3624c7959..36b9660d4e 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -65,14 +65,19 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen)
// the real merging done in earlier games. If we use the copying over, we
// will get issues because some views have marked all colors as being used
// and those will overwrite the current palette in that case
- if (getSciVersion() < SCI_VERSION_1_1)
+ if (getSciVersion() < SCI_VERSION_1_1) {
_useMerging = true;
- else if (getSciVersion() == SCI_VERSION_1_1)
+ _use16bitColorMatch = true;
+ } else if (getSciVersion() == SCI_VERSION_1_1) {
// there are some games that use inbetween SCI1.1 interpreter, so we have
// to detect if the current game is merging or copying
_useMerging = _resMan->detectPaletteMergingSci11();
- else // SCI32
+ _use16bitColorMatch = _useMerging;
+ } else {
+ // SCI32
_useMerging = false;
+ _use16bitColorMatch = false; // not verified that SCI32 uses 8-bit color matching
+ }
palVaryInit();
@@ -120,6 +125,10 @@ bool GfxPalette::isMerging() {
return _useMerging;
}
+bool GfxPalette::isUsing16bitColorMatch() {
+ return _use16bitColorMatch;
+}
+
// meant to get called only once during init of engine
void GfxPalette::setDefault() {
if (_resMan->getViewType() == kViewEga)
@@ -520,6 +529,15 @@ uint16 GfxPalette::matchColor(byte r, byte g, byte b) {
dr = _sysPalette.colors[i].r - r;
dg = _sysPalette.colors[i].g - g;
db = _sysPalette.colors[i].b - b;
+ if (!_use16bitColorMatch) {
+ // remove upper bits for most SCI1.1 games
+ // this bug was introduced with Quest For Glory 3 interpreter
+ // we have to implement it, otherwise some colors will be "wrong"
+ // See Space Quest 5 bug #6455
+ dr &= 0xFF;
+ dg &= 0xFF;
+ db &= 0xFF;
+ }
// minimum squares match
cdiff = (dr*dr) + (dg*dg) + (db*db);
// minimum sum match (Sierra's)
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 347695deb8..93cc2a8189 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -46,6 +46,7 @@ public:
~GfxPalette();
bool isMerging();
+ bool isUsing16bitColorMatch();
void setDefault();
void createFromData(byte *data, int bytesLeft, Palette *paletteOut);
@@ -124,6 +125,7 @@ private:
bool _sysPaletteChanged;
bool _useMerging;
+ bool _use16bitColorMatch;
Common::Array<PalSchedule> _schedules;
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index f3f352e5b8..a88546e68c 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -283,6 +283,7 @@ void GfxView::initData(GuiResourceId resourceId) {
_isScaleable = false;
break;
case 0x40:
+ case 0x4F: // LSL6 Polish, seems to be garbage - bug #6718
case 0:
break; // don't do anything, we already have _isScaleable set
default:
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 3344b79e26..000b037b44 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -535,10 +535,7 @@ bool Vocabulary::tokenizeString(ResultWordListList &retval, const char *sentence
if (Common::isAlnum(c) || (c == '-' && wordLen) || (c >= 0x80)) {
currentWord[wordLen] = lowerCaseMap[c];
++wordLen;
- } else if (c == '\'' && wordLen && (sentence[pos_in_sentence] == 's' || sentence[pos_in_sentence] == 'S')) {
- // Skip apostrophe-s at the end of the word, if it exists
- pos_in_sentence++; // skip the 's'
- } else {
+ } else if (c == ' ' || c == '\0') {
// Continue on this word. Words may contain a '-', but may not start with
// one.
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 17195c14b8..d155792853 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -55,6 +55,11 @@ SciVersion getSciVersion() {
return s_sciVersion;
}
+SciVersion getSciVersionForDetection() {
+ assert(!g_sci);
+ return s_sciVersion;
+}
+
const char *getSciVersionDesc(SciVersion version) {
switch (version) {
case SCI_VERSION_NONE:
@@ -88,9 +93,6 @@ const char *getSciVersionDesc(SciVersion version) {
//////////////////////////////////////////////////////////////////////
-
-#undef SCI_REQUIRE_RESOURCE_FILES
-
//#define SCI_VERBOSE_RESMAN 1
static const char *const s_errorDescriptions[] = {
@@ -639,7 +641,7 @@ int ResourceManager::addAppropriateSources() {
return 1;
}
-int ResourceManager::addAppropriateSources(const Common::FSList &fslist) {
+int ResourceManager::addAppropriateSourcesForDetection(const Common::FSList &fslist) {
ResourceSource *map = 0;
Common::Array<ResourceSource *> sci21Maps;
@@ -858,7 +860,7 @@ void ResourceManager::freeResourceSources() {
ResourceManager::ResourceManager() {
}
-void ResourceManager::init(bool initFromFallbackDetector) {
+void ResourceManager::init() {
_memoryLocked = 0;
_memoryLRU = 0;
_LRU.clear();
@@ -890,25 +892,24 @@ void ResourceManager::init(bool initFromFallbackDetector) {
debugC(1, kDebugLevelResMan, "resMan: Detected volume version %d: %s", _volVersion, versionDescription(_volVersion));
if ((_mapVersion == kResVersionUnknown) && (_volVersion == kResVersionUnknown)) {
- warning("Volume and map version not detected, assuming that this is not a sci game");
+ warning("Volume and map version not detected, assuming that this is not a SCI game");
_viewType = kViewUnknown;
return;
}
scanNewSources();
- if (!initFromFallbackDetector) {
- if (!addAudioSources()) {
- // FIXME: This error message is not always correct.
- // OTOH, it is nice to be able to detect missing files/sources
- // So we should definitely fix addAudioSources so this error
- // only pops up when necessary. Disabling for now.
- //error("Somehow I can't seem to find the sound files I need (RESOURCE.AUD/RESOURCE.SFX), aborting");
- }
- addScriptChunkSources();
- scanNewSources();
+ if (!addAudioSources()) {
+ // FIXME: This error message is not always correct.
+ // OTOH, it is nice to be able to detect missing files/sources
+ // So we should definitely fix addAudioSources so this error
+ // only pops up when necessary. Disabling for now.
+ //error("Somehow I can't seem to find the sound files I need (RESOURCE.AUD/RESOURCE.SFX), aborting");
}
+ addScriptChunkSources();
+ scanNewSources();
+
detectSciVersion();
debugC(1, kDebugLevelResMan, "resMan: Detected %s", getSciVersionDesc(getSciVersion()));
@@ -943,6 +944,22 @@ void ResourceManager::init(bool initFromFallbackDetector) {
}
}
+void ResourceManager::initForDetection() {
+ assert(!g_sci);
+
+ _memoryLocked = 0;
+ _memoryLRU = 0;
+ _LRU.clear();
+ _resMap.clear();
+ _audioMapSCI1 = NULL;
+
+ _mapVersion = detectMapVersion();
+ _volVersion = detectVolVersion();
+
+ scanNewSources();
+ detectSciVersion();
+}
+
ResourceManager::~ResourceManager() {
// freeing resources
ResourceMap::iterator itr = _resMap.begin();
@@ -1645,6 +1662,9 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
do {
type = fileStream->readByte() & 0x1F;
resMap[type].wOffset = fileStream->readUint16LE();
+ if (fileStream->eos())
+ return SCI_ERROR_RESMAP_NOT_FOUND;
+
resMap[prevtype].wSize = (resMap[type].wOffset
- resMap[prevtype].wOffset) / nEntrySize;
prevtype = type;
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index e90f52a3ce..62f3c584ac 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -312,10 +312,22 @@ public:
/**
* Initializes the resource manager.
*/
- void init(bool initFromFallbackDetector = false);
+ void init();
+ /**
+ * Similar to the function above, only called from the fallback detector
+ */
+ void initForDetection();
+
+ /**
+ * Adds all of the resource files for a game
+ */
int addAppropriateSources();
- int addAppropriateSources(const Common::FSList &fslist); // TODO: Switch from FSList to Common::Archive?
+
+ /**
+ * Similar to the function above, only called from the fallback detector
+ */
+ int addAppropriateSourcesForDetection(const Common::FSList &fslist); // TODO: Switch from FSList to Common::Archive?
/**
* Looks up a resource's data.
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 4c7cd9b84a..66778f0914 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -710,7 +710,6 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
// 0x20 is set on rhythm channels to prevent remapping
// CHECKME: Which SCI versions need that set manually?
- channel->flags = (*channel->data) >> 4;
if (channel->number == 9)
channel->flags |= 2;
// Note: flag 1: channel start offset is 0 instead of 10
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 48bc4819d2..2377386c72 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -429,6 +429,12 @@ extern SciEngine *g_sci;
SciVersion getSciVersion();
/**
+ * Same as above, but this version doesn't assert on unknown SCI versions.
+ * Only used by the fallback detector
+ */
+SciVersion getSciVersionForDetection();
+
+/**
* Convenience function converting an SCI version into a human-readable string.
*/
const char *getSciVersionDesc(SciVersion version);
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 80a72b9a6f..baf85de74c 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -399,24 +399,42 @@ void MidiPlayer_Midi::playSwitch(bool play) {
}
bool MidiPlayer_Midi::isMt32GmPatch(const byte *data, int size) {
- if (size < 1155)
+ // WORKAROUND: Some Mac games (e.g. LSL5) may have an extra byte at the
+ // end, so compensate for that here - bug #6725.
+ if (size == 16890)
+ size--;
+
+ // Need at least 1153 + 2 bytes for a GM patch. Check readMt32GmPatch()
+ // below for more info.
+ if (size < 1153 + 2)
return false;
+ // The maximum number of bytes for an MT-32 patch is 16889. The maximum
+ // number of timbres is 64, which leads us to:
+ // 491 + 1 + 64 * 246 + 653 = 16889
if (size > 16889)
return true;
bool isMt32 = false;
bool isMt32Gm = false;
+ // First, check for a GM patch. The presence of MIDI data after the
+ // initial 1153 + 2 bytes indicates a GM patch
if (READ_LE_UINT16(data + 1153) + 1155 == size)
isMt32Gm = true;
- int pos = 492 + 246 * data[491];
+ // Now check for a regular MT-32 patch. Check readMt32Patch() below for
+ // more info.
+ // 491 = 20 + 20 + 20 + 2 + 1 + 11 + 3 * 11 + 256 + 128
+ byte timbresNr = data[491];
+ int pos = 492 + 246 * timbresNr;
+ // Patches 49-96
if ((size >= (pos + 386)) && (READ_BE_UINT16(data + pos) == 0xabcd))
- pos += 386;
+ pos += 386; // 256 + 128 + 2
+ // Rhythm key map + partial reserve
if ((size >= (pos + 267)) && (READ_BE_UINT16(data + pos) == 0xdcba))
- pos += 267;
+ pos += 267; // 256 + 9 + 2
if (size == pos)
isMt32 = true;
@@ -460,10 +478,28 @@ void MidiPlayer_Midi::sendMt32SysEx(const uint32 addr, const byte *buf, int len,
}
void MidiPlayer_Midi::readMt32Patch(const byte *data, int size) {
+ // MT-32 patch contents:
+ // - 20 bytes unkown
+ // - 20 bytes before-SysEx message
+ // - 20 bytes goodbye SysEx message
+ // - 2 bytes volume
+ // - 1 byte reverb
+ // - 11 bytes reverb Sysex message
+ // - 3 * 11 reverb data
+ // - 256 + 128 bytes patches 1-48
+ // --> total: 491 bytes
+ // - 1 byte number of timbres (64 max)
+ // - 246 * timbres timbre data
+ // - 2 bytes flag (0xabcd)
+ // - 256 + 128 bytes patches 49-96
+ // - 2 bytes flag (0xdcba)
+ // - 256 bytes rhythm key map
+ // - 9 bytes partial reserve
+
Common::MemoryReadStream *str = new Common::MemoryReadStream(data, size);
// Send before-SysEx text
- str->seek(0x14);
+ str->seek(20);
sendMt32SysEx(0x200000, str, 20);
// Save goodbye message
@@ -527,15 +563,25 @@ void MidiPlayer_Midi::readMt32Patch(const byte *data, int size) {
}
void MidiPlayer_Midi::readMt32GmPatch(const byte *data, int size) {
- memcpy(_patchMap, data, 0x80);
- memcpy(_keyShift, data + 0x80, 0x80);
- memcpy(_volAdjust, data + 0x100, 0x80);
- memcpy(_percussionMap, data + 0x180, 0x80);
- _channels[MIDI_RHYTHM_CHANNEL].volAdjust = data[0x200];
- memcpy(_velocityMapIdx, data + 0x201, 0x80);
- memcpy(_velocityMap, data + 0x281, 0x200);
-
- uint16 midiSize = READ_LE_UINT16(data + 0x481);
+ // GM patch contents:
+ // - 128 bytes patch map
+ // - 128 bytes key shift
+ // - 128 bytes volume adjustment
+ // - 128 bytes percussion map
+ // - 1 byte volume adjust for the rhythm channel
+ // - 128 bytes velocity map IDs
+ // - 512 bytes velocity map
+ // --> total: 1153 bytes
+
+ memcpy(_patchMap, data, 128);
+ memcpy(_keyShift, data + 128, 128);
+ memcpy(_volAdjust, data + 256, 128);
+ memcpy(_percussionMap, data + 384, 128);
+ _channels[MIDI_RHYTHM_CHANNEL].volAdjust = data[512];
+ memcpy(_velocityMapIdx, data + 513, 128);
+ memcpy(_velocityMap, data + 641, 512);
+
+ uint16 midiSize = READ_LE_UINT16(data + 1153);
if (midiSize > 0) {
if (size < midiSize + 1155)
diff --git a/engines/scumm/POTFILES b/engines/scumm/POTFILES
index 6034320259..6d10537d3c 100644
--- a/engines/scumm/POTFILES
+++ b/engines/scumm/POTFILES
@@ -1,3 +1,6 @@
engines/scumm/dialogs.cpp
engines/scumm/help.cpp
engines/scumm/scumm.cpp
+engines/scumm/players/player_v3m.cpp
+engines/scumm/players/player_v5m.cpp
+
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 7cd50e1f4c..a7922b232e 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -504,12 +504,6 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF
dr.extra = "V1 Demo";
}
- // HACK: If 'Demo' occurs in the extra string, set the GF_DEMO flag,
- // required by some game demos (e.g. Dig, FT and COMI).
- if (dr.extra && strstr(dr.extra, "Demo")) {
- dr.game.features |= GF_DEMO;
- }
-
// HACK: Try to detect languages for translated games
if (dr.language == UNK_LANG) {
dr.language = detectLanguage(fslist, dr.game.id);
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index ae334c201c..3f08f17aff 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -260,13 +260,16 @@ static const GameSettings gameVariantsTable[] = {
{"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO1(GUIO_NOSPEECH)},
#ifdef ENABLE_SCUMM_7_8
- {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"ft", "", 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"ft", "Demo", 0, GID_FT, 7, 0, MDT_NONE, GF_DEMO, UNK, GUIO1(GUIO_NOMIDI)},
- {"dig", "", 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"dig", "", 0, GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
+ {"dig", "Demo", 0, GID_DIG, 7, 0, MDT_NONE, GF_DEMO, UNK, GUIO1(GUIO_NOMIDI)},
{"dig", "Steam", "steam", GID_DIG, 7, 0, MDT_NONE, 0, UNK, GUIO1(GUIO_NOMIDI)},
- {"comi", 0, 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
-#endif
+ {"comi", "", 0, GID_CMI, 8, 0, MDT_NONE, 0, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
+ {"comi", "Demo", 0, GID_CMI, 8, 0, MDT_NONE, GF_DEMO, Common::kPlatformWindows, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)},
+ #endif
// Humongous Entertainment Scumm Version 6
{"activity", "", 0, GID_HEGAME, 6, 62, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO1(GUIO_NOLAUNCHLOAD)},
@@ -677,12 +680,13 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "freddi", "Freddi Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "freddi", "Freddi Fish", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "freddi", "FreddiD", kGenHEPC, Common::NL_NLD, UNK, 0 },
+ { "freddi", "FreddiE", kGenHEPC, UNK_LANG, UNK, 0 },
{ "freddi", "Freddi Fisk", kGenHEMac, Common::SE_SWE, Common::kPlatformMacintosh, 0 },
{ "freddi", "FRITZI", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "freddi", "Marine Malice", kGenHEMac, Common::FR_FRA, Common::kPlatformMacintosh, 0 },
{ "freddi", "MM-DEMO", kGenHEPC, UNK_LANG, UNK, 0 },
- { "freddi2", "freddi2", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "freddi2", "freddi2", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "freddi2", "FF2-demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "freddi2", "ff2-demo", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "freddi2", "FFHSDemo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
@@ -744,7 +748,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "lost", "lost", kGenHEPC, UNK_LANG, UNK, 0 },
{ "lost", "Lost and Found", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
{ "lost", "smaller", kGenHEPC, UNK_LANG, UNK, 0 },
- { "lost", "verloren", kGenHEPC, Common::NL_NLD, UNK, 0 },
+ { "lost", "verloren", kGenHEPC, Common::NL_NLD, Common::kPlatformWindows, 0 },
{ "lost", "Verloren", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "maze", "maze", kGenHEPC, UNK_LANG, UNK, 0 },
@@ -789,7 +793,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "pajama2", "PJ2 Demo", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "pajama2", "PS2DEMO", kGenHEPC, Common::HE_ISR, UNK, 0 },
- { "pajama3", "pajama3", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "pajama3", "pajama3", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
{ "pajama3", "FPJ3Demo", kGenHEPC, Common::FR_FRA, UNK, 0 },
{ "pajama3", "GPJ3Demo", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "pajama3", "PajamaHTF", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
@@ -888,7 +892,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "socks", "socks", kGenHEPC, UNK_LANG, UNK, 0 },
{ "socks", "SockWorks", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 },
- { "socks", "SokkenSoep", kGenHEPC, Common::NL_NLD, UNK, 0 },
+ { "socks", "SokkenSoep", kGenHEPC, Common::NL_NLD, Common::kPlatformWindows, 0 },
{ "socks", "SokkenSoep", kGenHEMac, Common::NL_NLD, Common::kPlatformMacintosh, 0 },
{ "spyfox", "spyfox", kGenHEPC, UNK_LANG, Common::kPlatformWindows, 0 },
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index 7919075d0b..db836467ef 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -1013,7 +1013,6 @@ void ScummEngine::resetRoomObject(ObjectData *od, const byte *room, const byte *
od->actordir = (byte)READ_LE_UINT16(&imhd->v7.actordir);
} else if (_game.version == 6) {
- assert(imhd);
od->obj_nr = READ_LE_UINT16(&(cdhd->v6.obj_id));
od->width = READ_LE_UINT16(&cdhd->v6.w);
diff --git a/engines/scumm/players/player_mac.cpp b/engines/scumm/players/player_mac.cpp
index fe15698494..634fd2de2b 100644
--- a/engines/scumm/players/player_mac.cpp
+++ b/engines/scumm/players/player_mac.cpp
@@ -21,7 +21,6 @@
*/
#include "common/macresman.h"
-#include "common/translation.h"
#include "engines/engine.h"
#include "gui/message.h"
#include "scumm/players/player_mac.h"
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 0eeff57ff7..d7ec9bb686 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Wed Jun 25 10:34:07 2014
+ This file was generated by the md5table tool on Mon Oct 20 12:17:31 2014
DO NOT EDIT MANUALLY!
*/
@@ -28,7 +28,7 @@ static const MD5Table md5table[] = {
{ "055ffe4f47753e47594ac67823220c54", "puttrace", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "057c9b456dedcc4d71b991a3072a20b3", "monkey", "SEGA", "", 9465, Common::JA_JPN, Common::kPlatformSegaCD },
{ "06b187468113f9ae5a400b148a847fac", "atlantis", "Floppy", "Floppy", 12075, Common::EN_ANY, Common::kPlatformMacintosh },
- { "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
+ { "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", 79382, Common::NL_NLD, Common::kPlatformUnknown },
{ "07433205acdca3bc553d0e731588b35f", "airport", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "07a1eefd8ca95d77310311446c0f53d0", "brstorm", "", "", 5433, Common::EN_ANY, Common::kPlatformUnknown },
{ "07b810e37be7489263f7bc7627d4765d", "freddi4", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows },
@@ -112,7 +112,7 @@ static const MD5Table md5table[] = {
{ "2108d83dcf09f8adb4bc524669c8cf51", "PuttTime", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "21a6592322f92550f144f68a8a4e685e", "dig", "", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
{ "21abe302e1b1e2b66d6f5c12e241ebfd", "freddicove", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows },
- { "2232b0b9411575b1f9961713ebc9de61", "balloon", "HE 80", "", -1, Common::UNK_LANG, Common::kPlatformWindows },
+ { "2232b0b9411575b1f9961713ebc9de61", "balloon", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "225e18566e810c634bf7de63e7568e3e", "mustard", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "22c9eb04455440131ffc157aeb8d40a8", "fbear", "HE 70", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "22de86b2f7ec6e5db745ed1123310b44", "spyfox2", "", "Demo", 15832, Common::FR_FRA, Common::kPlatformWindows },
@@ -393,9 +393,10 @@ static const MD5Table md5table[] = {
{ "8e3241ddd6c8dadf64305e8740d45e13", "balloon", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "8e4ee4db46954bfe2912e259a16fad82", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "8e9417564f33790815445b2136efa667", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh },
- { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
+ { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", 65305, Common::NL_NLD, Common::kPlatformUnknown },
{ "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", 9925, Common::EN_ANY, Common::kPlatformFMTowns },
{ "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown },
+ { "8f345db2f3f5a25ed6305001957e6f72", "freddicove", "HE 100", "", 41182, Common::NL_NLD, Common::kPlatformUnknown },
{ "8f3758ff98c9c5d78e5d635222cad026", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformDOS },
{ "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", 18041, Common::UNK_LANG, Common::kPlatformWindows },
{ "8ffd618a776a4c0d8922bb28b09f8ce8", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
diff --git a/engines/sword1/POTFILES b/engines/sword1/POTFILES
index 849bef9060..b60d55ff22 100644
--- a/engines/sword1/POTFILES
+++ b/engines/sword1/POTFILES
@@ -1,4 +1,4 @@
engines/sword1/animation.cpp
engines/sword1/control.cpp
engines/sword1/logic.cpp
-engines/sword1/sword1.cpp
+
diff --git a/engines/sword1/console.cpp b/engines/sword1/console.cpp
index 3eb3b93a19..7fabc62192 100644
--- a/engines/sword1/console.cpp
+++ b/engines/sword1/console.cpp
@@ -22,14 +22,37 @@
#include "sword1/console.h"
#include "sword1/sword1.h"
+#include "sword1/sound.h"
+#include "common/config-manager.h"
+#include "common/str.h"
namespace Sword1 {
SwordConsole::SwordConsole(SwordEngine *vm) : GUI::Debugger(), _vm(vm) {
assert(_vm);
+ if (scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") == 0 || scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") == 0)
+ registerCmd("speechEndianness", WRAP_METHOD(SwordConsole, Cmd_SpeechEndianness));
}
SwordConsole::~SwordConsole() {
}
+
+bool SwordConsole::Cmd_SpeechEndianness(int argc, const char **argv) {
+ if (argc == 1) {
+ debugPrintf("Using %s speech\n", _vm->_sound->_bigEndianSpeech ? "be" : "le");
+ return true;
+ }
+ if (argc == 2) {
+ if (scumm_stricmp(argv[1], "le") == 0) {
+ _vm->_sound->_bigEndianSpeech = false;
+ return false;
+ } else if (scumm_stricmp(argv[1], "be") == 0) {
+ _vm->_sound->_bigEndianSpeech = true;
+ return false;
+ }
+ }
+ debugPrintf("Usage: %s [le | be]\n", argv[0]);
+ return true;
+}
} // End of namespace Sword
diff --git a/engines/sword1/console.h b/engines/sword1/console.h
index a2bb51f9a4..88ee756151 100644
--- a/engines/sword1/console.h
+++ b/engines/sword1/console.h
@@ -36,6 +36,7 @@ public:
private:
SwordEngine *_vm;
+ bool Cmd_SpeechEndianness(int argc, const char **argv);
};
} // End of namespace Sword1
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index ddde7f4235..9140bddb65 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -116,7 +116,7 @@ void Sound::checkSpeechFileEndianness() {
return;
// I picked the sample to use randomly (I just made sure it is long enough so that there is
- // a fair change of the heuristic to have a stable result and work for every language).
+ // a fair chance of the heuristic to have a stable result and work for every language).
int roomNo = _currentCowFile == 1 ? 1 : 129;
int localNo = _currentCowFile == 1 ? 2 : 933;
// Get the speech data and apply the heuristic
@@ -128,37 +128,42 @@ void Sound::checkSpeechFileEndianness() {
// Compute average of difference between two consecutive samples for both BE and LE
_bigEndianSpeech = false;
int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
- if (data) {
- if (size > 4000)
- size = 2000;
- else
- size /= 2;
- double le_diff_sum = 0.;
- for (uint32 i = 1; i < size; ++i)
- le_diff_sum += fabs((double)(data[i] - data[i - 1]));
- delete[] data;
- _bigEndianSpeech = true;
- data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
- if (data) {
- if (size > 4000)
- size = 2000;
- else
- size /= 2;
- double be_diff_sum = 0.;
- for (uint32 i = 1; i < size; ++i)
- be_diff_sum += fabs((double)(data[i] - data[i - 1]));
- delete [] data;
- // Set the big endian flag
- _bigEndianSpeech = (be_diff_sum < le_diff_sum);
- if (_bigEndianSpeech)
- debug(6, "Mac version: using big endian speech file");
- else
- debug(6, "Mac version: using little endian speech file");
- debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE, computed on %d samples)", be_diff_sum / (size - 1), le_diff_sum / (size - 1), size);
- } else
- _bigEndianSpeech = false;
+ uint32 maxSamples = size > 2000 ? 2000 : size;
+ double le_diff = endiannessHeuristicValue(data, size, maxSamples);
+ delete[] data;
+ _bigEndianSpeech = true;
+ data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
+ double be_diff = endiannessHeuristicValue(data, size, maxSamples);
+ delete [] data;
+ // Set the big endian flag
+ _bigEndianSpeech = (be_diff < le_diff);
+ if (_bigEndianSpeech)
+ debug(6, "Mac version: using big endian speech file");
+ else
+ debug(6, "Mac version: using little endian speech file");
+ debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE (%d samples)", be_diff, le_diff, maxSamples);
+ }
+}
+
+double Sound::endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples) {
+ if (!data)
+ return 50000.; // the heuristic value for the wrong endianess is about 21000 (1/3rd of the 16 bits range)
+
+ double diff_sum = 0.;
+ uint32 cpt = 0;
+ int16 prev_value = (int16)FROM_LE_16(*((uint16 *)(data)));
+ for (uint32 i = 1; i < dataSize && cpt < maxSamples; ++i) {
+ int16 value = (int16)FROM_LE_16(*((uint16 *)(data + i)));
+ if (value != prev_value) {
+ diff_sum += fabs((double)(value - prev_value));
+ ++cpt;
+ prev_value = value;
}
}
+ if (cpt == 0)
+ return 50000.;
+ maxSamples = cpt;
+ return diff_sum / cpt;
}
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 666598dba0..e65e797934 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -79,6 +79,7 @@ enum CowMode {
};
class Sound {
+ friend class SwordConsole;
public:
Sound(Audio::Mixer *mixer, ResMan *pResMan);
~Sound();
@@ -101,6 +102,7 @@ public:
void engine();
void checkSpeechFileEndianness();
+ double endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples);
private:
uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 08ea02f32d..1e9b7f70f4 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -774,6 +774,8 @@ void SwordEngine::reinitRes() {
_logic->newScreen(Logic::_scriptVars[NEW_SCREEN]);
_sound->newScreen(Logic::_scriptVars[NEW_SCREEN]);
Logic::_scriptVars[SCREEN] = Logic::_scriptVars[NEW_SCREEN];
+ _logic->engine();
+ _logic->updateScreenParams();
_screen->fullRefresh();
_screen->draw();
}
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index c58e97e353..eb24ef70fa 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -79,6 +79,7 @@ struct SystemVars {
};
class SwordEngine : public Engine {
+ friend class SwordConsole;
public:
SwordEngine(OSystem *syst);
virtual ~SwordEngine();
diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp
index fb83b7f941..7d68081593 100644
--- a/engines/sword25/kernel/persistenceservice.cpp
+++ b/engines/sword25/kernel/persistenceservice.cpp
@@ -52,7 +52,7 @@ static const uint SLOT_COUNT = 18;
static const uint FILE_COPY_BUFFER_SIZE = 1024 * 10;
static const char *VERSIONIDOLD = "SCUMMVM1";
static const char *VERSIONID = "SCUMMVM2";
-static const int VERSIONNUM = 2;
+static const int VERSIONNUM = 3;
#define MAX_SAVEGAME_SIZE 100
diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp
index fb477c1687..78b0a815e8 100644
--- a/engines/sword25/util/pluto/pluto.cpp
+++ b/engines/sword25/util/pluto/pluto.cpp
@@ -835,7 +835,15 @@ static void persistthread(PersistInfo *pi)
#endif
write_size(pi, &stackbase);
write_size(pi, &stacktop);
+
+ // ptrdiff_t changes sizes based on 32/64 bit
+ // Hard cast to 64 bit size if SIZE64 is defined
+#ifdef SIZES64
+ uint64 ptrIndex = static_cast<uint64>(L2->errfunc);
+ pi_write(pi, &ptrIndex, sizeof(uint64), pi->ud);
+#else
pi_write(pi, &L2->errfunc, sizeof(ptrdiff_t), pi->ud);
+#endif
//write_size(pi, (size_t *)&L2->errfunc);
}
@@ -944,12 +952,6 @@ static void persist(PersistInfo *pi)
if(!lua_isnil(pi->L, -1)) {
/* perms reftbl ... obj ref */
int zero = 0;
- // FIXME: Casting a pointer to an integer data type is a bad idea we
- // should really get rid of this by fixing the design of this code.
- // For now casting to size_t should silence most (all?) compilers,
- // since size_t is supposedly the same size as a pointer on most
- // (modern) architectures.
- int ref = (int)(size_t)lua_touserdata(pi->L, -1);
pi_write(pi, &zero, sizeof(int), pi->ud);
if (humanReadable) {
snprintf(hrBuf, hrBufSize, "persist_seenobject\n");
@@ -958,7 +960,8 @@ static void persist(PersistInfo *pi)
#ifdef TOTEXT
printf("persist_seenobject\n");
#endif
- pi_write(pi, &ref, sizeof(int), pi->ud);
+ int *ref = (int *)lua_touserdata(pi->L, -1);
+ pi_write(pi, ref, sizeof(int), pi->ud);
if (humanReadable) {
snprintf(hrBuf, hrBufSize, "persist_touserdata_ref %d\n", ref);
hrOut(pi);
@@ -1011,7 +1014,8 @@ static void persist(PersistInfo *pi)
}
lua_pushvalue(pi->L, -1);
/* perms reftbl ... obj obj */
- lua_pushlightuserdata(pi->L, (void *)(++(pi->counter)));
+ int *ref = (int *)lua_newuserdata(pi->L, sizeof(int));
+ *ref = ++(pi->counter);
/* perms reftbl ... obj obj ref */
lua_rawset(pi->L, 2);
/* perms reftbl ... obj */
@@ -1737,7 +1741,16 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
verify(LIF(Z,read)(&upi->zio, &L2->status, sizeof(lu_byte)) == 0);
read_size(&upi->zio, &stackbase);
read_size(&upi->zio, &stacktop);
+
+#ifdef SIZES64
+ uint64 value;
+ verify(LIF(Z,read)(&upi->zio, &value, sizeof(uint64)) == 0);
+
+ L2->errfunc = static_cast<ptrdiff_t>(value);
+#else
verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0);
+#endif
+
//read_size(&upi->zio, (size_t *)&L2->errfunc);
L2->base = L2->stack + stackbase;
L2->top = L2->stack + stacktop;
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 31610a8467..57d8432f0e 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -821,7 +821,8 @@ const char *const TinselEngine::_textFiles[][3] = {
TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) :
- Engine(syst), _gameDescription(gameDesc), _random("tinsel") {
+ Engine(syst), _gameDescription(gameDesc), _random("tinsel"),
+ _sound(0), _midiMusic(0), _pcmMusic(0), _bmv(0) {
_vm = this;
_config = new Config(this);
@@ -846,13 +847,6 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
if (cd_num >= 0)
_system->getAudioCDManager()->openCD(cd_num);
- _midiMusic = new MidiMusicPlayer();
- _pcmMusic = new PCMMusicPlayer();
-
- _sound = new SoundManager(this);
-
- _bmv = new BMVPlayer();
-
_mousePos.x = 0;
_mousePos.y = 0;
_keyHandler = NULL;
@@ -896,6 +890,11 @@ void TinselEngine::initializePath(const Common::FSNode &gamePath) {
}
Common::Error TinselEngine::run() {
+ _midiMusic = new MidiMusicPlayer();
+ _pcmMusic = new PCMMusicPlayer();
+ _sound = new SoundManager(this);
+ _bmv = new BMVPlayer();
+
// Initialize backend
if (getGameID() == GID_DW2) {
#ifndef DW2_EXACT_SIZE
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 97a14e5bc1..1d0e136d69 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -24,7 +24,6 @@
#include "engines/advancedDetector.h"
#include "common/savefile.h"
#include "common/system.h"
-#include "common/translation.h"
#include "base/plugins.h"
diff --git a/engines/tsage/POTFILES b/engines/tsage/POTFILES
new file mode 100644
index 0000000000..de18cbd072
--- /dev/null
+++ b/engines/tsage/POTFILES
@@ -0,0 +1,3 @@
+engines/tsage/dialogs.cpp
+engines/tsage/scenes.cpp
+
diff --git a/engines/tsage/blue_force/blueforce_dialogs.cpp b/engines/tsage/blue_force/blueforce_dialogs.cpp
index 2f337ac549..5be27c9ae7 100644
--- a/engines/tsage/blue_force/blueforce_dialogs.cpp
+++ b/engines/tsage/blue_force/blueforce_dialogs.cpp
@@ -20,8 +20,6 @@
*
*/
-#include "common/translation.h"
-
#include "gui/dialog.h"
#include "gui/widget.h"
diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp
index b647807f8a..a38796717a 100644
--- a/engines/tsage/debugger.cpp
+++ b/engines/tsage/debugger.cpp
@@ -42,7 +42,7 @@ Debugger::Debugger() : GUI::Debugger() {
registerCmd("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject));
registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots));
registerCmd("sound", WRAP_METHOD(Debugger, Cmd_Sound));
- registerCmd("setdebug", WRAP_METHOD(Debugger, Cmd_SetDebug));
+ registerCmd("setdebug", WRAP_METHOD(Debugger, Cmd_SetOutpostAlphaDebug));
}
static int strToInt(const char *s) {
@@ -344,7 +344,7 @@ bool Debugger::Cmd_Sound(int argc, const char **argv) {
/**
* Activate internal debugger, when available
*/
-bool Debugger::Cmd_SetDebug(int argc, const char **argv) {
+bool Debugger::Cmd_SetOutpostAlphaDebug(int argc, const char **argv) {
debugPrintf("Not available in this game\n");
return true;
}
@@ -720,7 +720,7 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) {
/**
* Activate internal debugger, when available
*/
-bool Ringworld2Debugger::Cmd_SetDebug(int argc, const char **argv) {
+bool Ringworld2Debugger::Cmd_SetOutpostAlphaDebug(int argc, const char **argv) {
if (argc != 1) {
debugPrintf("Usage: %s\n", argv[0]);
return true;
diff --git a/engines/tsage/debugger.h b/engines/tsage/debugger.h
index 610f45de64..b0f4c665dd 100644
--- a/engines/tsage/debugger.h
+++ b/engines/tsage/debugger.h
@@ -45,7 +45,7 @@ protected:
bool Cmd_Sound(int argc, const char **argv);
virtual bool Cmd_ListObjects(int argc, const char **argv) = 0;
virtual bool Cmd_MoveObject(int argc, const char **argv) = 0;
- virtual bool Cmd_SetDebug(int argc, const char **argv);
+ virtual bool Cmd_SetOutpostAlphaDebug(int argc, const char **argv);
};
class DemoDebugger : public Debugger {
@@ -70,7 +70,7 @@ class Ringworld2Debugger : public Debugger {
protected:
virtual bool Cmd_ListObjects(int argc, const char **argv);
virtual bool Cmd_MoveObject(int argc, const char **argv);
- virtual bool Cmd_SetDebug(int argc, const char **argv);
+ virtual bool Cmd_SetOutpostAlphaDebug(int argc, const char **argv);
};
} // End of namespace TsAGE
diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk
index 53c03e2e57..d62f398c20 100644
--- a/engines/tsage/module.mk
+++ b/engines/tsage/module.mk
@@ -35,13 +35,16 @@ MODULE_OBJS := \
ringworld/ringworld_scenes8.o \
ringworld/ringworld_scenes10.o \
ringworld/ringworld_speakers.o \
+ ringworld2/ringworld2_airduct.o \
ringworld2/ringworld2_dialogs.o \
ringworld2/ringworld2_logic.o \
+ ringworld2/ringworld2_outpost.o \
ringworld2/ringworld2_scenes0.o \
ringworld2/ringworld2_scenes1.o \
ringworld2/ringworld2_scenes2.o \
ringworld2/ringworld2_scenes3.o \
ringworld2/ringworld2_speakers.o \
+ ringworld2/ringworld2_vampire.o \
saveload.o \
scenes.o \
sound.o \
diff --git a/engines/tsage/ringworld/ringworld_dialogs.cpp b/engines/tsage/ringworld/ringworld_dialogs.cpp
index 226a943f08..1dd3bc158b 100644
--- a/engines/tsage/ringworld/ringworld_dialogs.cpp
+++ b/engines/tsage/ringworld/ringworld_dialogs.cpp
@@ -20,8 +20,6 @@
*
*/
-#include "common/translation.h"
-
#include "gui/dialog.h"
#include "gui/widget.h"
diff --git a/engines/tsage/ringworld2/ringworld2_airduct.cpp b/engines/tsage/ringworld2/ringworld2_airduct.cpp
new file mode 100644
index 0000000000..136e8d5d1b
--- /dev/null
+++ b/engines/tsage/ringworld2/ringworld2_airduct.cpp
@@ -0,0 +1,909 @@
+/* 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 "tsage/ringworld2/ringworld2_airduct.h"
+
+namespace TsAGE {
+
+namespace Ringworld2 {
+
+/*--------------------------------------------------------------------------
+ * Scene 1200 - Air Ducts Maze
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene1200::Scene1200() {
+ _nextCrawlDirection = 0;
+ _field414 = 0;
+ _field416 = 0;
+ _field418 = 0;
+ _field41A = 0;
+ _fixupMaze = false;
+}
+
+void Scene1200::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_nextCrawlDirection);
+ s.syncAsSint16LE(_field414);
+ s.syncAsSint16LE(_field416);
+ s.syncAsSint16LE(_field418);
+ s.syncAsSint16LE(_field41A);
+ s.syncAsSint16LE(_fixupMaze);
+}
+
+Scene1200::LaserPanel::LaserPanel() {
+}
+
+void Scene1200::LaserPanel::Jumper::init(int state) {
+ _state = state;
+
+ SceneActor::postInit();
+ setup(1003, 1, 1);
+ fixPriority(255);
+
+ switch (_state) {
+ case 1:
+ switch (R2_GLOBALS._ductMazePanel1State) {
+ case 1:
+ setFrame2(2);
+ setPosition(Common::Point(129, 101));
+ break;
+ case 2:
+ setFrame2(3);
+ setPosition(Common::Point(135, 95));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 2:
+ switch (R2_GLOBALS._ductMazePanel2State) {
+ case 1:
+ setFrame2(2);
+ setPosition(Common::Point(152, 101));
+ break;
+ case 2:
+ setFrame2(3);
+ setPosition(Common::Point(158, 122));
+ break;
+ case 3:
+ setFrame2(3);
+ setPosition(Common::Point(135, 122));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 3:
+ switch (R2_GLOBALS._ductMazePanel3State) {
+ case 1:
+ setFrame2(3);
+ setPosition(Common::Point(158, 95));
+ break;
+ case 2:
+ setFrame2(2);
+ setPosition(Common::Point(175, 101));
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ setDetails(1200, 12, -1, -1, 2, (SceneItem *) NULL);
+}
+
+bool Scene1200::LaserPanel::Jumper::startAction(CursorType action, Event &event) {
+ if (action != CURSOR_USE)
+ return SceneActor::startAction(action, event);
+
+ R2_GLOBALS._sound2.play(260);
+ switch (_state) {
+ case 1:
+ if (R2_GLOBALS._ductMazePanel1State == 1) {
+ R2_GLOBALS._ductMazePanel1State = 2;
+ setFrame2(3);
+ setPosition(Common::Point(135, 95));
+ } else {
+ R2_GLOBALS._ductMazePanel1State = 1;
+ setFrame2(2);
+ setPosition(Common::Point(129, 101));
+ }
+ break;
+ case 2:
+ ++R2_GLOBALS._ductMazePanel2State;
+ if (R2_GLOBALS._ductMazePanel2State == 4)
+ R2_GLOBALS._ductMazePanel2State = 1;
+
+ switch (R2_GLOBALS._ductMazePanel2State) {
+ case 1:
+ setFrame2(2);
+ setPosition(Common::Point(152, 101));
+ break;
+ case 2:
+ setFrame2(3);
+ setPosition(Common::Point(158, 122));
+ break;
+ case 3:
+ setFrame2(3);
+ setPosition(Common::Point(135, 122));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 3:
+ if (R2_GLOBALS._ductMazePanel3State == 1) {
+ R2_GLOBALS._ductMazePanel3State = 2;
+ setFrame2(2);
+ setPosition(Common::Point(175, 101));
+ } else {
+ R2_GLOBALS._ductMazePanel3State = 1;
+ setFrame2(3);
+ setPosition(Common::Point(158, 95));
+ }
+ break;
+ default:
+ break;
+ }
+
+ Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
+ scene->_field418 = 0;
+
+ if ((R2_GLOBALS._ductMazePanel1State == 1) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
+ scene->_field418 = 1;
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
+ scene->_field418 = 2;
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 2))
+ scene->_field418 = 3;
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 3) && (R2_GLOBALS._ductMazePanel3State == 1))
+ scene->_field418 = 4;
+
+ return true;
+}
+
+void Scene1200::LaserPanel::postInit(SceneObjectList *OwnerList) {
+ Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_field41A = 1;
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
+ setup2(1003, 1, 1, 100, 40);
+ setup3(1200, 11, -1, -1);
+ R2_GLOBALS._sound2.play(259);
+ _jumper1.init(1);
+ _jumper2.init(2);
+ _jumper3.init(3);
+
+ R2_GLOBALS._player._canWalk = false;
+}
+
+void Scene1200::LaserPanel::remove() {
+ Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_field41A = 0;
+ scene->_sceneAreas.remove(&_jumper1);
+ scene->_sceneAreas.remove(&_jumper2);
+ scene->_sceneAreas.remove(&_jumper3);
+ _jumper1.remove();
+ _jumper2.remove();
+ _jumper3.remove();
+
+ ModalWindow::remove();
+ R2_GLOBALS._player._canWalk = true;
+}
+
+void Scene1200::postInit(SceneObjectList *OwnerList) {
+ loadScene(1200);
+ SceneExt::postInit();
+
+ if (R2_GLOBALS._sceneManager._previousScene < 3200)
+ R2_GLOBALS._sound1.play(257);
+
+ _nextCrawlDirection = CRAWL_EAST;
+ _field414 = 0;
+ _field416 = 0;
+ _field418 = 0;
+ _field41A = 0;
+
+ if ((R2_GLOBALS._ductMazePanel1State == 1) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
+ _field418 = 1;
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
+ _field418 = 2;
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 2))
+ _field418 = 3;
+ else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 3) && (R2_GLOBALS._ductMazePanel3State == 1))
+ _field418 = 4;
+
+ R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.disableControl();
+ R2_GLOBALS._player.setup(3156, 1, 6);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 70));
+ R2_GLOBALS._player._numFrames = 10;
+ R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 1200;
+
+ _actor1.postInit();
+ _actor1.hide();
+
+ _mazeUI.setDisplayBounds(Rect(110, 20, 210, 120));
+
+ _mazeUI.postInit();
+ _mazeUI.load(1);
+ _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
+
+ R2_GLOBALS._player.enableControl();
+ _item1.setDetails(Rect(0, 0, 320, 200), 1200, 0, 1, 2, 1, NULL);
+}
+
+void Scene1200::signal() {
+ switch (_sceneMode++) {
+ case 1:
+ // No break on purpose
+ case 1200:
+ // No break on purpose
+ case 1201:
+ // No break on purpose
+ case 1202:
+ // No break on purpose
+ case 1203:
+ R2_GLOBALS._player.enableControl();
+ // CHECKME: The original is calling _eventManager.waitEvent();
+ _sceneMode = 2;
+ break;
+ case 10:
+ _field416 = 1;
+ _field414 = 6;
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.setStrip(1);
+ R2_GLOBALS._player.setFrame(5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 11:
+ // No break on purpose
+ case 21:
+ // No break on purpose
+ case 31:
+ // No break on purpose
+ case 41:
+ _field416 = 0;
+ break;
+ case 12:
+ _field414 = 14;
+ R2_GLOBALS._player._numFrames = 10;
+ R2_GLOBALS._player.setup(3155, 1, 4);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 70));
+ R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
+ break;
+ case 13:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 23:
+ // No break on purpose
+ case 26:
+ // No break on purpose
+ case 33:
+ // No break on purpose
+ case 36:
+ // No break on purpose
+ case 43:
+ // No break on purpose
+ case 46:
+ R2_GLOBALS._player.setFrame(4);
+ _sceneMode = 1;
+ setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
+ break;
+ case 15:
+ // No break on purpose
+ case 25:
+ // No break on purpose
+ case 35:
+ // No break on purpose
+ case 45:
+ _field414 = 20;
+ R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
+ break;
+ case 20:
+ _field416 = 1;
+ _field414 = 6;
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.setStrip(2);
+ R2_GLOBALS._player.setFrame(5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 22:
+ _field414 = 14;
+ R2_GLOBALS._player._numFrames = 10;
+ R2_GLOBALS._player.setup(3155, 2, 4);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 70));
+ R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
+ break;
+ case 30:
+ _field416 = 1;
+ _field414 = 6;
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.setStrip(3);
+ R2_GLOBALS._player.setFrame(5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 32:
+ _field414 = 14;
+ R2_GLOBALS._player._numFrames = 10;
+ R2_GLOBALS._player.setup(3155, 3, 4);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 70));
+ R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
+ break;
+ case 40:
+ _field416 = 1;
+ _field414 = 6;
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.setStrip(4);
+ R2_GLOBALS._player.setFrame(5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 42:
+ _field414 = 14;
+ R2_GLOBALS._player._numFrames = 10;
+ R2_GLOBALS._player.setup(3155, 4, 4);
+ R2_GLOBALS._player.setPosition(Common::Point(160, 70));
+ R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
+ break;
+ case 50:
+ // No break on purpose
+ case 55:
+ // No break on purpose
+ case 60:
+ R2_GLOBALS._player.setup(3156, 5, 1);
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 51:
+ // No break on purpose
+ case 56:
+ // No break on purpose
+ case 117:
+ R2_GLOBALS._player.setup(3157, 1, 1);
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 52:
+ // No break on purpose
+ case 82:
+ // No break on purpose
+ case 118:
+ R2_GLOBALS._player.setup(3156, 3, 6);
+ _sceneMode = 1;
+ setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
+ break;
+ case 57:
+ // No break on purpose
+ case 91:
+ // No break on purpose
+ case 96:
+ R2_GLOBALS._player.setup(3157, 2, 1);
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 58:
+ // No break on purpose
+ case 92:
+ // No break on purpose
+ case 122:
+ R2_GLOBALS._player.setup(3156, 2, 6);
+ _sceneMode = 1;
+ setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
+ break;
+ case 61:
+ R2_GLOBALS._player.setup(3157, 4, 5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 62:
+ // No break on purpose
+ case 72:
+ // No break on purpose
+ case 98:
+ R2_GLOBALS._player.setup(3156, 4, 6);
+ _sceneMode = 1;
+ setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
+ break;
+ case 70:
+ // No break on purpose
+ case 75:
+ // No break on purpose
+ case 80:
+ R2_GLOBALS._player.setup(3156, 6, 1);
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 71:
+ // No break on purpose
+ case 76:
+ // No break on purpose
+ case 97:
+ R2_GLOBALS._player.setup(3157, 3, 1);
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 77:
+ // No break on purpose
+ case 111:
+ // No break on purpose
+ case 116:
+ R2_GLOBALS._player.setup(3157, 4, 1);
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 78:
+ // No break on purpose
+ case 102:
+ // No break on purpose
+ case 112:
+ R2_GLOBALS._player.setup(3156, 1, 6);
+ _sceneMode = 1;
+ setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
+ break;
+ case 81:
+ R2_GLOBALS._player.setup(3157, 2, 5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 90:
+ // No break on purpose
+ case 95:
+ // No break on purpose
+ case 100:
+ R2_GLOBALS._player.setup(3156, 7, 1);
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 101:
+ R2_GLOBALS._player.setup(3157, 1, 5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ case 110:
+ // No break on purpose
+ case 115:
+ // No break on purpose
+ case 120:
+ R2_GLOBALS._player.setup(3156, 8, 1);
+ R2_GLOBALS._player._numFrames = 5;
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ break;
+ case 121:
+ R2_GLOBALS._player.setup(3157, 3, 5);
+ R2_GLOBALS._player.animate(ANIM_MODE_6, this);
+ break;
+ default:
+ // CHECKME: The original is walling _eventManager.waitEvent();
+ _sceneMode = 2;
+ break;
+ }
+}
+
+void Scene1200::process(Event &event) {
+ if (_field414 != 0)
+ return;
+
+ Scene::process(event);
+
+ if (!R2_GLOBALS._player._canWalk)
+ return;
+
+ if (event.eventType == EVENT_BUTTON_DOWN) {
+ Common::Point cellPos = R2_GLOBALS._ventCellPos;
+ _mazeUI.pixelToCellXY(cellPos);
+
+ int cellId = _mazeUI.getCellFromPixelXY(event.mousePos);
+ switch (R2_GLOBALS._events.getCursor()) {
+ case CURSOR_WALK:
+ event.handled = true;
+ if ((event.mousePos.x > 179) && (event.mousePos.x < 210) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
+ startCrawling(CRAWL_EAST);
+
+ if ((event.mousePos.x > 109) && (event.mousePos.x < 140) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
+ startCrawling(CRAWL_WEST);
+
+ if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 89) && (event.mousePos.y < 120))
+ startCrawling(CRAWL_SOUTH);
+
+ if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 19) && (event.mousePos.y < 50))
+ startCrawling(CRAWL_NORTH);
+ break;
+ case CURSOR_USE:
+ if (cellId > 36) {
+ if ( ((cellPos.x == 3) && (cellPos.y == 33))
+ || ((cellPos.x == 7) && (cellPos.y == 33))
+ || ((cellPos.x == 33) && (cellPos.y == 41))
+ || ((cellPos.x == 5) && (cellPos.y == 5))
+ || ((cellPos.x == 13) && (cellPos.y == 21))
+ || ((cellPos.x == 17) && (cellPos.y == 21))
+ || ((cellPos.x == 17) && (cellPos.y == 5))
+ || ((cellPos.x == 17) && (cellPos.y == 9))
+ || ((cellPos.x == 29) && (cellPos.y == 17))
+ || ((cellPos.x == 33) && (cellPos.y == 17))
+ || ((cellPos.x == 35) && (cellPos.y == 17))
+ || ((cellPos.x == 41) && (cellPos.y == 21)) ) {
+ _laserPanel.postInit();
+ event.handled = true;
+ }
+ }
+
+ if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
+ if ( ((cellPos.x == 3) && (cellPos.y == 9))
+ || ((cellPos.x == 11) && (cellPos.y == 27))
+ || ((cellPos.x == 17) && (cellPos.y == 7))
+ || ((cellPos.x == 17) && (cellPos.y == 27))
+ || ((cellPos.x == 17) && (cellPos.y == 33))
+ || (cellPos.x == 33) ) {
+ switch (cellPos.x) {
+ case 3:
+ R2_GLOBALS._sceneManager.changeScene(3150);
+ break;
+ case 33:
+ if (R2_GLOBALS._scientistConvIndex >= 4)
+ R2_GLOBALS._sceneManager.changeScene(3250);
+ else
+ SceneItem::display(1200, 6, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
+ break;
+ default:
+ SceneItem::display(1200, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
+ break;
+ }
+ event.handled = true;
+ }
+ }
+ break;
+ case CURSOR_LOOK:
+ if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
+ event.handled = true;
+ switch (cellPos.x) {
+ case 3:
+ // It was your cell.
+ SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ break;
+ case 9:
+ R2_GLOBALS._sceneManager.changeScene(3240);
+ break;
+ case 11:
+ if (cellPos.y == 27)
+ R2_GLOBALS._sceneManager.changeScene(3210);
+ else
+ // A vent grill
+ SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ break;
+ case 17:
+ switch (cellPos.y) {
+ case 5:
+ R2_GLOBALS._sceneManager.changeScene(3230);
+ break;
+ case 21:
+ R2_GLOBALS._sceneManager.changeScene(3220);
+ break;
+ case 33:
+ R2_GLOBALS._sceneManager.changeScene(3200);
+ break;
+ default:
+ // A vent grill
+ SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ break;
+ }
+ break;
+ case 33:
+ R2_GLOBALS._sceneManager.changeScene(3245);
+ break;
+ default:
+ SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ break;
+ }
+ }
+ if (cellId > 36) {
+ // "An anti-pest laser"
+ event.handled = true;
+ SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ }
+ break;
+ case CURSOR_TALK:
+ event.handled = true;
+ break;
+ default:
+ return;
+ }
+ } else if (event.eventType == EVENT_KEYPRESS) {
+ if (_field414) {
+ event.handled = false;
+ return;
+ }
+
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_UP:
+ startCrawling(CRAWL_NORTH);
+ break;
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_LEFT:
+ startCrawling(CRAWL_WEST);
+ break;
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_RIGHT:
+ startCrawling(CRAWL_EAST);
+ break;
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_DOWN:
+ startCrawling(CRAWL_SOUTH);
+ break;
+ default:
+ event.handled = false;
+ return;
+ break;
+ }
+ } else
+ return;
+}
+
+void Scene1200::dispatch() {
+ Rect tmpRect;
+ Scene::dispatch();
+
+ if (_fixupMaze) {
+ _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
+ //_mazeUI.draw();
+ _fixupMaze = false;
+ }
+
+ if (_field414 != 0) {
+ tmpRect.set(110, 20, 210, 120);
+ _field414--;
+
+ switch (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ R2_GLOBALS._ventCellPos.x += 2;
+ break;
+ case CRAWL_WEST:
+ R2_GLOBALS._ventCellPos.x -= 2;
+ break;
+ case CRAWL_SOUTH:
+ R2_GLOBALS._ventCellPos.y += 2;
+ break;
+ case CRAWL_NORTH:
+ R2_GLOBALS._ventCellPos.y -= 2;
+ break;
+ default:
+ break;
+ }
+
+ _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
+ //_mazeUI.draw();
+
+ if (_field416 != 0) {
+ switch(_nextCrawlDirection) {
+ case CRAWL_EAST:
+ R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x - 2, R2_GLOBALS._player._position.y));
+ break;
+ case CRAWL_WEST:
+ R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x + 2, R2_GLOBALS._player._position.y));
+ break;
+ case CRAWL_SOUTH:
+ R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y - 2));
+ break;
+ case CRAWL_NORTH:
+ R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 2));
+ break;
+ default:
+ break;
+ }
+ }
+ if (_field414 == 0) {
+ if (_field416 == 0)
+ R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL);
+ signal();
+ }
+ }
+}
+
+void Scene1200::saveCharacter(int characterIndex) {
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ SceneExt::saveCharacter(characterIndex);
+}
+
+void Scene1200::startCrawling(CrawlDirection dir) {
+ Common::Point cellPos = R2_GLOBALS._ventCellPos;
+ _mazeUI.pixelToCellXY(cellPos);
+
+ switch (dir) {
+ case CRAWL_EAST:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(200, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(200, 88)) > 36))
+ && ( ((cellPos.x == 3) && (cellPos.y == 33) && (_field418 != 4))
+ || ((cellPos.x == 13) && (cellPos.y == 21) && (_field418 != 2))
+ || ((cellPos.x == 29) && (cellPos.y == 17) && (_field418 != 1))
+ || ((cellPos.x == 33) && (cellPos.y == 41)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1200;
+ setAction(&_sequenceManager, this, 1200, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(200, 69)) == 36) {
+ switch (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 15;
+ else
+ _sceneMode = 10;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 76;
+ else
+ _sceneMode = 75;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 101;
+ else
+ _sceneMode = 100;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 111;
+ else
+ _sceneMode = 110;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 1;
+ signal();
+ }
+ break;
+ case CRAWL_WEST:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(120, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(120, 88)) > 36))
+ && ( ((cellPos.x == 7) && (cellPos.y == 33) && (_field418 != 4))
+ || ((cellPos.x == 17) && (cellPos.y == 21) && (_field418 != 2))
+ || ((cellPos.x == 33) && (cellPos.y == 17) && (_field418 != 1))
+ || ((cellPos.x == 5) && (cellPos.y == 5)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1201;
+ setAction(&_sequenceManager, this, 1201, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(120, 69)) == 36) {
+ switch (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 56;
+ else
+ _sceneMode = 55;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 25;
+ else
+ _sceneMode = 20;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 91;
+ else
+ _sceneMode = 90;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 121;
+ else
+ _sceneMode = 120;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 2;
+ signal();
+ }
+ break;
+ case CRAWL_SOUTH:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 110)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 110)) > 36))
+ && ( ((cellPos.x == 17) && (cellPos.y == 5) && (_field418 != 3))
+ || ((cellPos.x == 41) && (cellPos.y == 21)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1203;
+ setAction(&_sequenceManager, this, 1203, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 110)) == 36) {
+ switch (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 51;
+ else
+ _sceneMode = 50;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 81;
+ else
+ _sceneMode = 80;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 35;
+ else
+ _sceneMode = 30;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 116;
+ else
+ _sceneMode = 115;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 3;
+ signal();
+ }
+ break;
+ case CRAWL_NORTH:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 30)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 30)) > 36))
+ && ( ((cellPos.x == 17) && (cellPos.y == 9) && (_field418 != 3))
+ || ((cellPos.x == 35) && (cellPos.y == 17)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1202;
+ setAction(&_sequenceManager, this, 1202, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 30)) == 36) {
+ switch (_nextCrawlDirection) {
+ case CRAWL_EAST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 61;
+ else
+ _sceneMode = 60;
+ break;
+ case CRAWL_WEST:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 71;
+ else
+ _sceneMode = 70;
+ break;
+ case CRAWL_SOUTH:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 96;
+ else
+ _sceneMode = 95;
+ break;
+ case CRAWL_NORTH:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 45;
+ else
+ _sceneMode = 40;
+ break;
+ default:
+ _sceneMode = 1;
+ R2_GLOBALS._player.setup(3156, 4, 6);
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _nextCrawlDirection = 4;
+ signal();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+} // End of namespace Ringworld2
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_airduct.h b/engines/tsage/ringworld2/ringworld2_airduct.h
new file mode 100644
index 0000000000..89dfe778d0
--- /dev/null
+++ b/engines/tsage/ringworld2/ringworld2_airduct.h
@@ -0,0 +1,89 @@
+/* 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.
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD2_AIRDUCT_H
+#define TSAGE_RINGWORLD2_AIRDUCT_H
+
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/sound.h"
+#include "tsage/ringworld2/ringworld2_logic.h"
+
+namespace TsAGE {
+
+namespace Ringworld2 {
+
+using namespace TsAGE;
+
+class Scene1200 : public SceneExt {
+ enum CrawlDirection { CRAWL_EAST = 1, CRAWL_WEST = 2, CRAWL_SOUTH = 3, CRAWL_NORTH = 4 };
+
+ class LaserPanel: public ModalWindow {
+ public:
+ class Jumper : public SceneActorExt {
+ public:
+ void init(int state);
+ virtual bool startAction(CursorType action, Event &event);
+ };
+
+ Jumper _jumper1;
+ Jumper _jumper2;
+ Jumper _jumper3;
+
+ LaserPanel();
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ };
+
+public:
+ NamedHotspot _item1;
+ SceneActor _actor1;
+ LaserPanel _laserPanel;
+ MazeUI _mazeUI;
+ SequenceManager _sequenceManager;
+
+ int _nextCrawlDirection;
+ int _field414;
+ int _field416;
+ int _field418;
+ int _field41A;
+ bool _fixupMaze;
+
+ Scene1200();
+ void synchronize(Serializer &s);
+
+ void startCrawling(CrawlDirection dir);
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+ virtual void process(Event &event);
+ virtual void dispatch();
+ virtual void saveCharacter(int characterIndex);
+};
+
+} // End of namespace Ringworld2
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index 99188c1ab6..d24541932f 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -32,6 +32,9 @@
#include "tsage/ringworld2/ringworld2_scenes1.h"
#include "tsage/ringworld2/ringworld2_scenes2.h"
#include "tsage/ringworld2/ringworld2_scenes3.h"
+#include "tsage/ringworld2/ringworld2_airduct.h"
+#include "tsage/ringworld2/ringworld2_outpost.h"
+#include "tsage/ringworld2/ringworld2_vampire.h"
namespace TsAGE {
@@ -355,6 +358,11 @@ SceneExt::SceneExt(): Scene() {
// to make inter-scene debugging easier, I'm explicitly resetting the _animationCtr
// on scene start, since scene objects aren't drawn while it's non-zero
R2_GLOBALS._animationCtr = 0;
+
+ // WORKAROUND: We had a case where at some point the number of modal dialogs
+ // open became incorrect. So reset it on scene changes to fix the problem if
+ // it ever happens
+ R2_GLOBALS._insetUp = 0;
}
void SceneExt::synchronize(Serializer &s) {
diff --git a/engines/tsage/ringworld2/ringworld2_outpost.cpp b/engines/tsage/ringworld2/ringworld2_outpost.cpp
new file mode 100644
index 0000000000..05cfa6259b
--- /dev/null
+++ b/engines/tsage/ringworld2/ringworld2_outpost.cpp
@@ -0,0 +1,4700 @@
+/* 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 "graphics/cursorman.h"
+#include "tsage/tsage.h"
+#include "tsage/staticres.h"
+#include "tsage/ringworld2/ringworld2_outpost.h"
+
+namespace TsAGE {
+
+namespace Ringworld2 {
+
+/*--------------------------------------------------------------------------
+ * Scene 1337 - Card game
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene1337::Card::Card() {
+ _cardId = 0;
+ _stationPos = Common::Point(0, 0);
+}
+
+void Scene1337::Card::synchronize(Serializer &s) {
+ _card.synchronize(s);
+
+ s.syncAsSint16LE(_cardId);
+ s.syncAsSint16LE(_stationPos.x);
+ s.syncAsSint16LE(_stationPos.y);
+}
+
+bool Scene1337::Card::isIn(Common::Point pt) {
+ if ((_stationPos.x > pt.x) || (_stationPos.x + 24 < pt.x))
+ return false;
+
+ if ((_stationPos.y > pt.y) || (_stationPos.y + 24 < pt.y))
+ return false;
+
+ return true;
+}
+
+Scene1337::GameBoardSide::GameBoardSide() {
+ _card1Pos = Common::Point(0, 0);
+ _card2Pos = Common::Point(0, 0);
+ _card3Pos = Common::Point(0, 0);
+ _card4Pos = Common::Point(0, 0);
+ _frameNum = 0;
+}
+
+void Scene1337::GameBoardSide::synchronize(Serializer &s) {
+ SceneHotspot::synchronize(s);
+
+ for (int i = 0; i < 4; i++)
+ _handCard[i].synchronize(s);
+
+ for (int i = 0; i < 8; i++)
+ _outpostStation[i].synchronize(s);
+
+ _delayCard.synchronize(s);
+ _emptyStationPos.synchronize(s);
+
+ s.syncAsSint16LE(_card1Pos.x);
+ s.syncAsSint16LE(_card1Pos.y);
+ s.syncAsSint16LE(_card2Pos.x);
+ s.syncAsSint16LE(_card2Pos.y);
+ s.syncAsSint16LE(_card3Pos.x);
+ s.syncAsSint16LE(_card3Pos.y);
+ s.syncAsSint16LE(_card4Pos.x);
+ s.syncAsSint16LE(_card4Pos.y);
+ s.syncAsSint16LE(_frameNum);
+}
+
+Scene1337::Scene1337() {
+ _autoplay = false;
+ _cardsAvailableNumb = 0;
+ _currentDiscardIndex = 0;
+
+ for (int i = 0; i < 100; i++)
+ _availableCardsPile[i] = 0;
+
+ _shuffleEndedFl = false;
+ _currentPlayerNumb = 0;
+ _actionPlayerIdx = 0;
+ _actionVictimIdx = 0;
+ _showPlayerTurn = false;
+ _displayHelpFl = false;
+ _winnerId = -1;
+ _instructionsDisplayedFl = false;
+ _instructionsWaitCount = 0;
+
+ _delayedFunction = nullptr;
+ _actionCard1 = nullptr;
+ _actionCard2 = nullptr;
+ _actionCard3 = nullptr;
+
+ _cursorCurRes = 0;
+ _cursorCurStrip = 0;
+ _cursorCurFrame = 0;
+}
+
+void Scene1337::synchronize(Serializer &s) {
+ _actionCard1->synchronize(s);
+ _actionCard2->synchronize(s);
+ _actionCard3->synchronize(s);
+ _animatedCard.synchronize(s);
+ _shuffleAnimation.synchronize(s);
+ _discardedPlatformCard.synchronize(s);
+ _selectedCard.synchronize(s);
+ _discardPile.synchronize(s);
+ _stockCard.synchronize(s);
+ _aSound1.synchronize(s);
+ _aSound2.synchronize(s);
+ _helpIcon.synchronize(s);
+ _stockPile.synchronize(s);
+ _actionItem.synchronize(s);
+ _currentPlayerArrow.synchronize(s);
+
+ for (int i = 0; i < 4; i++)
+ _gameBoardSide[i].synchronize(s);
+
+ for (int i = 0; i < 8; i++) {
+ _upperDisplayCard[i].synchronize(s);
+ _lowerDisplayCard[i].synchronize(s);
+ }
+
+ // TODO s.syncPointer(_delayedFunction);
+ s.syncAsByte(_autoplay);
+ s.syncAsByte(_shuffleEndedFl);
+ s.syncAsByte(_showPlayerTurn);
+ s.syncAsByte(_displayHelpFl);
+ s.syncAsByte(_instructionsDisplayedFl);
+ s.syncAsSint16LE(_currentDiscardIndex);
+ s.syncAsSint16LE(_cardsAvailableNumb);
+ s.syncAsSint16LE(_currentPlayerNumb);
+ s.syncAsSint16LE(_actionPlayerIdx);
+ s.syncAsSint16LE(_actionVictimIdx);
+ s.syncAsSint16LE(_winnerId);
+ s.syncAsSint16LE(_instructionsWaitCount);
+ s.syncAsSint16LE(_cursorCurRes);
+ s.syncAsSint16LE(_cursorCurStrip);
+ s.syncAsSint16LE(_cursorCurFrame);
+
+ for (int i = 0; i < 100; i++)
+ s.syncAsSint16LE(_availableCardsPile[i]);
+
+}
+
+void Scene1337::Action1337::waitFrames(int32 frameCount) {
+ uint32 firstFrameNumber = g_globals->_events.getFrameNumber();
+ uint32 curFrame = firstFrameNumber;
+ uint32 destFrame = firstFrameNumber + frameCount;
+
+ while ((curFrame < destFrame) && !g_vm->shouldQuit()) {
+ TsAGE::Event event;
+ g_globals->_events.getEvent(event);
+ curFrame = g_globals->_events.getFrameNumber();
+ }
+
+ // CHECKME: The original is calling _eventManager.waitEvent();
+}
+
+/**
+ * Display instructions
+ */
+void Scene1337::Action1::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 1: {
+ scene->actionDisplay(1331, 6, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ R2_GLOBALS._sceneObjects->draw();
+ scene->actionDisplay(1331, 7, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ scene->actionDisplay(1331, 8, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ scene->_gameBoardSide[1]._outpostStation[0]._cardId = 2;
+ scene->_gameBoardSide[1]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[1]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[1]._outpostStation[0]._cardId);
+ scene->_gameBoardSide[1]._outpostStation[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[1]._outpostStation[0]);
+
+ scene->_gameBoardSide[1]._outpostStation[1]._cardId = 3;
+ scene->_gameBoardSide[1]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[1]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[1]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[1]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[1]._outpostStation[1]);
+
+ scene->_gameBoardSide[2]._outpostStation[0]._cardId = 4;
+ scene->_gameBoardSide[2]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[0]._cardId);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[0]);
+
+ scene->_gameBoardSide[3]._outpostStation[0]._cardId = 5;
+ scene->_gameBoardSide[3]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[0]._cardId);
+ scene->_gameBoardSide[3]._outpostStation[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[0]);
+
+ scene->_gameBoardSide[3]._outpostStation[1]._cardId = 6;
+ scene->_gameBoardSide[3]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[3]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[1]);
+
+ scene->_gameBoardSide[3]._outpostStation[2]._cardId = 7;
+ scene->_gameBoardSide[3]._outpostStation[2]._card.postInit();
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[2]._stationPos, 0);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setStrip(2);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[2]._cardId);
+ scene->_gameBoardSide[3]._outpostStation[2]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[2]);
+
+ scene->_gameBoardSide[0]._outpostStation[0]._cardId = 8;
+ scene->_gameBoardSide[0]._outpostStation[0]._card.postInit();
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[0]._outpostStation[0]._stationPos, 0);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setStrip(2);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[0]._outpostStation[0]._cardId);
+ scene->_gameBoardSide[0]._outpostStation[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[0]._outpostStation[0]);
+
+ scene->_gameBoardSide[0]._outpostStation[1]._cardId = 9;
+ scene->_gameBoardSide[0]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[0]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[0]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[0]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[0]._outpostStation[1]);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(60);
+ scene->actionDisplay(1331, 9, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ scene->_gameBoardSide[2]._outpostStation[1]._cardId = 2;
+ scene->_gameBoardSide[2]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[1]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
+
+ scene->_gameBoardSide[2]._outpostStation[2]._cardId = 3;
+ scene->_gameBoardSide[2]._outpostStation[2]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[2]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[2]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[2]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[2]);
+
+ scene->_gameBoardSide[2]._outpostStation[3]._cardId = 5;
+ scene->_gameBoardSide[2]._outpostStation[3]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[3]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[3]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[3]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[3]);
+
+ scene->_gameBoardSide[2]._outpostStation[4]._cardId = 6;
+ scene->_gameBoardSide[2]._outpostStation[4]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[4]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[4]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[4]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[4]);
+
+ scene->_gameBoardSide[2]._outpostStation[5]._cardId = 7;
+ scene->_gameBoardSide[2]._outpostStation[5]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[5]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[5]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[5]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[5]);
+
+ scene->_gameBoardSide[2]._outpostStation[6]._cardId = 8;
+ scene->_gameBoardSide[2]._outpostStation[6]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[6]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[6]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[6]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[6]);
+
+ scene->_gameBoardSide[2]._outpostStation[7]._cardId = 9;
+ scene->_gameBoardSide[2]._outpostStation[7]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[7]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setStrip(2);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[7]._cardId);
+ scene->_gameBoardSide[2]._outpostStation[7]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[7]);
+
+ scene->_aSound1.play(62);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(120);
+ scene->_gameBoardSide[2]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[1]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[2]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[3]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[4]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[5]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[6]._card.remove();
+ scene->_gameBoardSide[2]._outpostStation[7]._card.remove();
+
+ scene->_gameBoardSide[1]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[1]._outpostStation[1]._card.remove();
+
+ scene->_gameBoardSide[3]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[3]._outpostStation[1]._card.remove();
+ scene->_gameBoardSide[3]._outpostStation[2]._card.remove();
+
+ scene->_gameBoardSide[0]._outpostStation[0]._card.remove();
+ scene->_gameBoardSide[0]._outpostStation[1]._card.remove();
+
+ scene->_stockPile.setup(1332, 5, 1);
+ scene->_stockPile.setPosition(Common::Point(162, 95));
+ scene->_stockPile.setPriority(110);
+ scene->_stockPile._effect = EFFECT_SHADED;
+ scene->_stockPile.show();
+
+ scene->_gameBoardSide[1]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[0]._card.setPosition(scene->_gameBoardSide[1]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[0]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[0]._card.fixPriority(170);
+
+ scene->_gameBoardSide[1]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[1]._card.setPosition(scene->_gameBoardSide[1]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[1]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[1]._card.fixPriority(170);
+
+ scene->_gameBoardSide[1]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[2]._card.setPosition(scene->_gameBoardSide[1]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[2]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[2]._card.fixPriority(170);
+
+ scene->_gameBoardSide[2]._handCard[0]._cardId = 30;
+ scene->_gameBoardSide[2]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[0]._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[0]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[0]);
+
+ scene->_gameBoardSide[2]._handCard[1]._cardId = 16;
+ scene->_gameBoardSide[2]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[1]._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[1]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[1]);
+
+ scene->_gameBoardSide[2]._handCard[2]._cardId = 1;
+ scene->_gameBoardSide[2]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[2]._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[2]._card.fixPriority(170);
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[2]);
+
+ scene->_gameBoardSide[3]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[0]._card.setPosition(scene->_gameBoardSide[3]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[0]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[0]._card.fixPriority(170);
+
+ scene->_gameBoardSide[3]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[1]._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[1]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[1]._card.fixPriority(170);
+
+ scene->_gameBoardSide[3]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[2]._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[2]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[2]._card.fixPriority(170);
+
+ scene->_gameBoardSide[0]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[0]._card.setPosition(scene->_gameBoardSide[0]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[0]._handCard[0]._card.setFrame(2);
+ scene->_gameBoardSide[0]._handCard[0]._card.fixPriority(170);
+
+ scene->_gameBoardSide[0]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[1]._card.setPosition(scene->_gameBoardSide[0]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[0]._handCard[1]._card.setFrame(2);
+ scene->_gameBoardSide[0]._handCard[1]._card.fixPriority(170);
+
+ scene->_gameBoardSide[0]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[2]._card.setPosition(scene->_gameBoardSide[0]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[0]._handCard[2]._card.setFrame(2);
+ scene->_gameBoardSide[0]._handCard[2]._card.fixPriority(170);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ scene->actionDisplay(1331, 10, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
+ scene->_animatedCard._card.show();
+ scene->_aSound2.play(61);
+
+ Common::Point pt(91, 174);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+ }
+ break;
+ case 2: {
+ scene->_gameBoardSide[2]._handCard[3]._cardId = 2;
+ scene->_gameBoardSide[2]._handCard[3]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[3]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[3]._card.setPosition(scene->_gameBoardSide[2]._handCard[3]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[3]._card.setStrip(1);
+ scene->_gameBoardSide[2]._handCard[3]._card.setFrame(2);
+ scene->_gameBoardSide[2]._handCard[3]._card.fixPriority(170);
+
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[3]);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(60);
+ scene->actionDisplay(1331, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ scene->actionDisplay(1331, 12, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ scene->_gameBoardSide[2]._outpostStation[1]._cardId = 1;
+ scene->_gameBoardSide[2]._outpostStation[1]._card.postInit();
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._outpostStation[1]._card.hide();
+
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[2]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._card._frame);
+ scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
+
+ scene->_gameBoardSide[2]._handCard[2]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[2]._card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._outpostStation[1]._stationPos, this);
+ }
+ break;
+ case 3: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
+ scene->_aSound1.play(59);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(60);
+ scene->actionDisplay(1331, 13, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ scene->_gameBoardSide[2]._outpostStation[1]._cardId = scene->_gameBoardSide[2]._handCard[3]._cardId;
+
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[3]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[3]._card._frame);
+
+ scene->_gameBoardSide[2]._handCard[3]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[3]._card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[3]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._outpostStation[1]._stationPos, this);
+ }
+ break;
+ case 4: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
+ scene->_aSound1.play(59);
+
+ scene->_discardPile._cardId = 1;
+ scene->_discardPile._card.hide();
+
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
+ }
+ break;
+ case 5: {
+ scene->_animatedCard._card.hide();
+
+ scene->_discardPile._card.postInit();
+ scene->_discardPile._card.setVisage(1332);
+ scene->_discardPile._card.setPosition(scene->_discardPile._stationPos, 0);
+ scene->setAnimationInfo(&scene->_discardPile);
+ scene->_aSound2.play(61);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(60);
+ scene->actionDisplay(1331, 14, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ scene->_gameBoardSide[2]._delayCard._card.postInit();
+ scene->_gameBoardSide[2]._delayCard._card.setVisage(1332);
+ scene->_gameBoardSide[2]._delayCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
+ scene->_gameBoardSide[2]._delayCard._card.hide();
+
+ scene->_gameBoardSide[3]._handCard[2]._cardId = 0;
+ scene->_gameBoardSide[3]._handCard[2].remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayCard._stationPos, this);
+ }
+ break;
+ case 6: {
+ scene->_animatedCard._card.hide();
+ scene->_gameBoardSide[2]._delayCard._cardId = 21;
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._delayCard);
+ scene->_aSound1.play(57);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(60);
+ scene->actionDisplay(1331, 15, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ int tmpVal = 15;
+ int i = -1;
+
+ for (i = 0; i <= 7; i++) {
+ tmpVal += 29;
+
+ scene->_upperDisplayCard[i].postInit();
+ scene->_upperDisplayCard[i].setVisage(1332);
+ scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 90), 0);
+ scene->_upperDisplayCard[i].setStrip(3);
+ scene->_upperDisplayCard[i].fixPriority(190);
+
+ scene->_lowerDisplayCard[i].postInit();
+ scene->_lowerDisplayCard[i].setVisage(1332);
+ scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 90), 0);
+ scene->_lowerDisplayCard[i].setStrip(7);
+ scene->_lowerDisplayCard[i].setFrame(1);
+ scene->_lowerDisplayCard[i].fixPriority(180);
+ }
+
+ scene->_upperDisplayCard[0].setFrame(1);
+ scene->_upperDisplayCard[1].setFrame(3);
+ scene->_upperDisplayCard[2].setFrame(6);
+ scene->_upperDisplayCard[3].setFrame(8);
+ scene->_upperDisplayCard[4].setFrame(9);
+ scene->_upperDisplayCard[5].setFrame(10);
+ scene->_upperDisplayCard[6].setFrame(11);
+ scene->_upperDisplayCard[7].setFrame(12);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(240);
+
+ scene->_upperDisplayCard[0].remove();
+ scene->_upperDisplayCard[1].remove();
+ scene->_upperDisplayCard[2].remove();
+ scene->_upperDisplayCard[3].remove();
+ scene->_upperDisplayCard[4].remove();
+ scene->_upperDisplayCard[5].remove();
+ scene->_upperDisplayCard[6].remove();
+ scene->_upperDisplayCard[7].remove();
+
+ scene->_lowerDisplayCard[0].remove();
+ scene->_lowerDisplayCard[1].remove();
+ scene->_lowerDisplayCard[2].remove();
+ scene->_lowerDisplayCard[3].remove();
+ scene->_lowerDisplayCard[4].remove();
+ scene->_lowerDisplayCard[5].remove();
+ scene->_lowerDisplayCard[6].remove();
+ scene->_lowerDisplayCard[7].remove();
+
+ scene->_discardPile._cardId = scene->_gameBoardSide[2]._delayCard._cardId;
+
+ scene->_gameBoardSide[2]._delayCard._cardId = 0;
+ scene->_gameBoardSide[2]._delayCard._card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
+ }
+ break;
+ case 7: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
+ scene->_aSound2.play(61);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ scene->_gameBoardSide[2]._delayCard._card.postInit();
+ scene->_gameBoardSide[2]._delayCard._card.setVisage(1332);
+ scene->_gameBoardSide[2]._delayCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
+ scene->_gameBoardSide[2]._delayCard._card.hide();
+
+ scene->_gameBoardSide[3]._handCard[1]._cardId = 0;
+ scene->_gameBoardSide[3]._handCard[1].remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayCard._stationPos, this);
+ }
+ break;
+ case 8: {
+ scene->_animatedCard._card.hide();
+ scene->_gameBoardSide[2]._delayCard._cardId = 14;
+ scene->setAnimationInfo(&scene->_gameBoardSide[2]._delayCard);
+ scene->_aSound1.play(57);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ scene->actionDisplay(1331, 16, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ int tmpVal = 72;
+ int i = -1;
+
+ for (i = 0; i <= 3; i++) {
+ tmpVal += 29;
+ scene->_upperDisplayCard[i].postInit();
+ scene->_upperDisplayCard[i].setVisage(1332);
+ scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 71), 0);
+ scene->_upperDisplayCard[i].setStrip(3);
+ scene->_upperDisplayCard[i].fixPriority(190);
+
+ scene->_lowerDisplayCard[i].postInit();
+ scene->_lowerDisplayCard[i].setVisage(1332);
+ scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 71), 0);
+ scene->_lowerDisplayCard[i].setStrip(7);
+ scene->_lowerDisplayCard[i].setFrame(1);
+ scene->_lowerDisplayCard[i].fixPriority(180);
+ }
+
+ scene->_upperDisplayCard[0].setFrame(2);
+ scene->_upperDisplayCard[1].setFrame(5);
+ scene->_upperDisplayCard[2].setFrame(7);
+ scene->_upperDisplayCard[3].setFrame(15);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(240);
+ scene->actionDisplay(1331, 17, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ tmpVal = 72;
+ for (i = 4; i <= 7; i++) {
+ tmpVal += 29;
+
+ scene->_upperDisplayCard[i].postInit();
+ scene->_upperDisplayCard[i].setVisage(1332);
+ scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 100), 0);
+ scene->_upperDisplayCard[i].setStrip(4);
+ scene->_upperDisplayCard[i].fixPriority(190);
+
+ scene->_lowerDisplayCard[i].postInit();
+ scene->_lowerDisplayCard[i].setVisage(1332);
+ scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 100), 0);
+ scene->_lowerDisplayCard[i].setStrip(7);
+ scene->_lowerDisplayCard[i].setFrame(1);
+ scene->_lowerDisplayCard[i].fixPriority(180);
+ }
+
+ scene->_upperDisplayCard[4].setFrame(1);
+ scene->_upperDisplayCard[5].setFrame(5);
+ scene->_upperDisplayCard[6].setFrame(7);
+ scene->_upperDisplayCard[7].setFrame(3);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(240);
+
+ scene->_upperDisplayCard[0].remove();
+ scene->_upperDisplayCard[1].remove();
+ scene->_upperDisplayCard[2].remove();
+ scene->_upperDisplayCard[3].remove();
+ scene->_upperDisplayCard[4].remove();
+ scene->_upperDisplayCard[5].remove();
+ scene->_upperDisplayCard[6].remove();
+ scene->_upperDisplayCard[7].remove();
+
+ scene->_lowerDisplayCard[0].remove();
+ scene->_lowerDisplayCard[1].remove();
+ scene->_lowerDisplayCard[2].remove();
+ scene->_lowerDisplayCard[3].remove();
+ scene->_lowerDisplayCard[4].remove();
+ scene->_lowerDisplayCard[5].remove();
+ scene->_lowerDisplayCard[6].remove();
+ scene->_lowerDisplayCard[7].remove();
+
+ scene->_discardPile._cardId = scene->_gameBoardSide[2]._handCard[0]._cardId;
+
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[0]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._card._frame);
+ scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
+
+ scene->_gameBoardSide[2]._handCard[0]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[0]._card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayCard._stationPos, this);
+ }
+ break;
+ case 9: {
+ scene->_aSound1.play(58);
+ scene->_gameBoardSide[2]._delayCard._cardId = 0;
+ scene->_gameBoardSide[2]._delayCard.remove();
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
+ }
+ break;
+ case 10: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
+ scene->_aSound2.play(61);
+
+ R2_GLOBALS._sceneObjects->draw();
+ scene->actionDisplay(1331, 18, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ scene->_upperDisplayCard[0].postInit();
+ scene->_upperDisplayCard[0].setVisage(1332);
+ scene->_upperDisplayCard[0].setPosition(Common::Point(131, 71), 0);
+ scene->_upperDisplayCard[0].fixPriority(190);
+ scene->_upperDisplayCard[0].setStrip(3);
+ scene->_upperDisplayCard[0].setFrame(4);
+
+ scene->_lowerDisplayCard[0].postInit();
+ scene->_lowerDisplayCard[0].setVisage(1332);
+ scene->_lowerDisplayCard[0].setPosition(Common::Point(131, 71), 0);
+ scene->_lowerDisplayCard[0].setStrip(7);
+ scene->_lowerDisplayCard[0].setFrame(1);
+ scene->_lowerDisplayCard[0].fixPriority(180);
+
+ scene->_upperDisplayCard[1].postInit();
+ scene->_upperDisplayCard[1].setVisage(1332);
+ scene->_upperDisplayCard[1].setPosition(Common::Point(160, 71), 0);
+ scene->_upperDisplayCard[1].fixPriority(190);
+ scene->_upperDisplayCard[1].setStrip(3);
+ scene->_upperDisplayCard[1].setFrame(16);
+
+ scene->_lowerDisplayCard[1].postInit();
+ scene->_lowerDisplayCard[1].setVisage(1332);
+ scene->_lowerDisplayCard[1].setPosition(Common::Point(160, 71), 0);
+ scene->_lowerDisplayCard[1].setStrip(7);
+ scene->_lowerDisplayCard[1].setFrame(1);
+ scene->_lowerDisplayCard[1].fixPriority(180);
+
+ scene->_upperDisplayCard[2].postInit();
+ scene->_upperDisplayCard[2].setVisage(1332);
+ scene->_upperDisplayCard[2].setPosition(Common::Point(131, 100), 0);
+ scene->_upperDisplayCard[2].fixPriority(190);
+ scene->_upperDisplayCard[2].setStrip(4);
+ scene->_upperDisplayCard[2].setFrame(4);
+
+ scene->_lowerDisplayCard[2].postInit();
+ scene->_lowerDisplayCard[2].setVisage(1332);
+ scene->_lowerDisplayCard[2].setPosition(Common::Point(131, 100), 0);
+ scene->_lowerDisplayCard[2].setStrip(7);
+ scene->_lowerDisplayCard[2].setFrame(1);
+ scene->_lowerDisplayCard[2].fixPriority(180);
+
+ scene->_upperDisplayCard[3].postInit();
+ scene->_upperDisplayCard[3].setVisage(1332);
+ scene->_upperDisplayCard[3].setPosition(Common::Point(160, 100), 0);
+ scene->_upperDisplayCard[3].fixPriority(190);
+ scene->_upperDisplayCard[3].setStrip(4);
+ scene->_upperDisplayCard[3].setFrame(2);
+
+ scene->_lowerDisplayCard[3].postInit();
+ scene->_lowerDisplayCard[3].setVisage(1332);
+ scene->_lowerDisplayCard[3].setPosition(Common::Point(160, 100), 0);
+ scene->_lowerDisplayCard[3].setStrip(7);
+ scene->_lowerDisplayCard[3].setFrame(1);
+ scene->_lowerDisplayCard[3].fixPriority(180);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ waitFrames(240);
+
+ scene->_upperDisplayCard[0].remove();
+ scene->_upperDisplayCard[1].remove();
+ scene->_upperDisplayCard[2].remove();
+ scene->_upperDisplayCard[3].remove();
+
+ scene->_lowerDisplayCard[0].remove();
+ scene->_lowerDisplayCard[1].remove();
+ scene->_lowerDisplayCard[2].remove();
+ scene->_lowerDisplayCard[3].remove();
+
+ scene->_currentPlayerArrow.setFrame(1);
+ scene->_currentPlayerArrow.show();
+ scene->_currentPlayerArrow.animate(ANIM_MODE_2, NULL);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ scene->actionDisplay(1331, 19, 159, 10, 1, 220, 0, 7, 0, 154, 154);
+
+ scene->_currentPlayerArrow.hide();
+
+ scene->actionDisplay(1331, 20, 159, 10, 1, 220, 0, 7, 0, 154, 154);
+ scene->actionDisplay(1331, 21, 159, 10, 1, 220, 0, 7, 0, 154, 154);
+
+ scene->_discardPile._cardId = scene->_gameBoardSide[2]._handCard[1]._cardId;
+
+ scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[1]._card._strip);
+ scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._card._frame);
+ scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
+
+ scene->_gameBoardSide[2]._handCard[1]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[1]._card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
+ }
+ break;
+ case 11: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
+ scene->_aSound2.play(61);
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
+
+ R2_GLOBALS._sceneObjects->draw();
+
+ scene->actionDisplay(1331, 22, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ int i = -1;
+ for (i = 0; i <= 3; i ++) {
+ scene->_gameBoardSide[3]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[3]._handCard[i]._card.remove();
+
+ scene->_gameBoardSide[2]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[2]._handCard[i]._card.remove();
+
+ scene->_gameBoardSide[0]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[0]._handCard[i]._card.remove();
+
+ scene->_gameBoardSide[1]._handCard[i]._cardId = 0;
+ scene->_gameBoardSide[1]._handCard[i]._card.remove();
+ }
+
+ for (i = 0; i <= 7; i++) {
+ scene->_gameBoardSide[3]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[3]._outpostStation[i]._card.remove();
+
+ scene->_gameBoardSide[2]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[2]._outpostStation[i]._card.remove();
+
+ scene->_gameBoardSide[0]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[0]._outpostStation[i]._card.remove();
+
+ scene->_gameBoardSide[1]._outpostStation[i]._cardId = 0;
+ scene->_gameBoardSide[1]._outpostStation[i]._card.remove();
+ }
+
+ scene->_gameBoardSide[2]._delayCard._cardId = 0;
+ scene->_gameBoardSide[2]._delayCard._card.remove();
+
+ scene->_discardPile._cardId = 0;
+ scene->_discardPile._card.remove();
+
+ scene->_stockPile.remove();
+ }
+ // No break on purpose
+ case 0:
+ R2_GLOBALS._sceneObjects->draw();
+ signal();
+ break;
+ case 12:
+ scene->suggestInstructions();
+ remove();
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Shuffle cards animation
+ */
+void Scene1337::Action2::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ scene->_shuffleAnimation._card.postInit();
+ scene->_shuffleAnimation._card.setVisage(1332);
+ scene->_shuffleAnimation._card.setStrip(8);
+ scene->_shuffleAnimation._card.setFrame(1);
+ scene->_shuffleAnimation._card.fixPriority(300);
+ scene->_shuffleAnimation._card.setPosition(Common::Point(156, 108));
+
+ scene->_discardPile._card.remove();
+ scene->_discardPile._cardId = 0;
+
+ scene->_aSound1.play(60);
+ scene->_shuffleAnimation._card.animate(ANIM_MODE_5, this);
+ break;
+ case 1:
+ scene->_shuffleAnimation._card.setFrame(1);
+
+ scene->_aSound1.play(60);
+ scene->_shuffleAnimation._card.animate(ANIM_MODE_5, this);
+ break;
+ case 2: {
+ Common::Point pt(156, 108);
+ NpcMover *mover = new NpcMover();
+ scene->_shuffleAnimation._card.addMover(mover, &pt, this);
+ }
+ break;
+ case 3:
+ scene->_shuffleAnimation._card.remove();
+ scene->_stockPile.setup(1332, 5, 1);
+ scene->_stockPile.setPosition(Common::Point(162, 95));
+ scene->_stockPile.setPriority(110);
+ scene->_stockPile._effect = EFFECT_SHADED;
+ scene->_stockPile.show();
+ scene->_shuffleEndedFl = true;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Deal cards
+ */
+void Scene1337::Action3::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_animatedCard._card._moveDiff = Common::Point(30, 30);
+ scene->_animatedCard._card.setVisage(1332);
+ scene->_animatedCard._card.setStrip(5);
+ scene->_animatedCard._card.setFrame(1);
+ scene->_animatedCard._card.fixPriority(400);
+ scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(283, 146);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_animatedCard._card.show();
+ scene->_gameBoardSide[1]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 1: {
+ scene->_gameBoardSide[1]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[1]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[0]._card.setPosition(scene->_gameBoardSide[1]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[0]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[0]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(10, 174);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[2]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 2: {
+ scene->_gameBoardSide[2]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[2]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[0]._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[0]._card.fixPriority(170);
+ if (scene->_gameBoardSide[2]._handCard[0]._cardId > 25) {
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(4);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId - 25);
+ } else if (scene->_gameBoardSide[2]._handCard[0]._cardId > 9) {
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(3);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId - 9);
+ } else {
+ scene->_gameBoardSide[2]._handCard[0]._card.setStrip(2);
+ scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId);
+ }
+ scene->_aSound2.play(61);
+
+ Common::Point pt(14, 14);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[3]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 3: {
+ scene->_gameBoardSide[3]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[3]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[0]._card.setPosition(scene->_gameBoardSide[3]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[0]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[0]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(280, 5);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[0]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 4: {
+ scene->_gameBoardSide[0]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[0]._card._moveDiff = Common::Point(30,30);
+ scene->_gameBoardSide[0]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[0]._card.setPosition(scene->_gameBoardSide[0]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[0]._card.setStrip(5);
+ scene->_gameBoardSide[0]._handCard[0]._card.setFrame(1);
+ scene->_gameBoardSide[0]._handCard[0]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(283, 124);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[1]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 5: {
+ scene->_gameBoardSide[1]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[1]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[1]._card.setPosition(scene->_gameBoardSide[1]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[1]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[1]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(37, 174);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[2]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 6: {
+ scene->_gameBoardSide[2]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[2]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[1]._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[1]._card.fixPriority(170);
+
+ if (scene->_gameBoardSide[2]._handCard[1]._cardId > 25) {
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(4);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId - 25);
+ } else if (scene->_gameBoardSide[2]._handCard[1]._cardId > 9) {
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(3);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId - 9);
+ } else {
+ scene->_gameBoardSide[2]._handCard[1]._card.setStrip(2);
+ scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId);
+ }
+
+ scene->_aSound2.play(61);
+
+ Common::Point pt(14, 36);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[3]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 7: {
+ scene->_gameBoardSide[3]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[3]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[1]._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos);
+ scene->_gameBoardSide[3]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[1]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[1]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(253, 5);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[0]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 8: {
+ scene->_gameBoardSide[0]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[0]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[1]._card.setPosition(scene->_gameBoardSide[0]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[1]._card.setStrip(5);
+ scene->_gameBoardSide[0]._handCard[1]._card.setFrame(1);
+ scene->_gameBoardSide[0]._handCard[1]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(283, 102);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[1]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 9: {
+ scene->_gameBoardSide[1]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[1]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[1]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[1]._handCard[2]._card.setPosition(scene->_gameBoardSide[1]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[1]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[1]._handCard[2]._card.setFrame(4);
+ scene->_gameBoardSide[1]._handCard[2]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(64, 174);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[2]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 10: {
+ scene->_gameBoardSide[2]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[2]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[2]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[2]._handCard[2]._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[2]._handCard[2]._card.fixPriority(170);
+
+ if (scene->_gameBoardSide[2]._handCard[2]._cardId > 25) {
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(4);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId - 25);
+ } else if (scene->_gameBoardSide[2]._handCard[2]._cardId > 9) {
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(3);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId - 9);
+ } else {
+ scene->_gameBoardSide[2]._handCard[2]._card.setStrip(2);
+ scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId);
+ }
+
+ scene->_aSound2.play(61);
+
+ Common::Point pt(14, 58);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[3]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 11: {
+ scene->_gameBoardSide[3]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[3]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[3]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[3]._handCard[2]._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[3]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[3]._handCard[2]._card.setFrame(3);
+ scene->_gameBoardSide[3]._handCard[2]._card.fixPriority(170);
+ scene->_aSound2.play(61);
+
+ Common::Point pt(226, 5);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+
+ scene->_gameBoardSide[0]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ }
+ break;
+ case 12:
+ scene->_gameBoardSide[0]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[0]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[0]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[0]._handCard[2]._card.setPosition(scene->_gameBoardSide[0]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[0]._handCard[2]._card.setStrip(5);
+ scene->_gameBoardSide[0]._handCard[2]._card.setFrame(1);
+ scene->_gameBoardSide[0]._handCard[2]._card.fixPriority(170);
+ scene->_animatedCard._card.hide();
+ default:
+ break;
+ }
+
+ if (_actionIndex > 12) {
+ scene->_currentPlayerNumb = 0;
+ R2_GLOBALS._sceneObjects->draw();
+ scene->actionDisplay(1330, 0, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ scene->handleNextTurn();
+ } else if (_actionIndex >= 1) {
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ }
+}
+
+/**
+ * Action used to handle the other players' turn
+ */
+void Scene1337::Action4::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId == 0)
+ && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
+ if (scene->_cardsAvailableNumb < 0)
+ scene->shuffleCards();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
+ scene->_animatedCard._card.show();
+ scene->_aSound2.play(61);
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card1Pos, this);
+
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+
+ if (scene->_cardsAvailableNumb < 0)
+ scene->_stockPile.remove();
+ } else {
+ // Self call, forcing next actionIndex
+ signal();
+ }
+ break;
+ case 1:
+ if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card1Pos.x)
+ && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card1Pos.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.fixPriority(170);
+ }
+
+ if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]);
+
+ scene->_animatedCard._card.hide();
+ if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._cardId == 0)
+ && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
+ if (scene->_cardsAvailableNumb < 0)
+ scene->shuffleCards();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95));
+ scene->_animatedCard._card.show();
+
+ scene->_aSound2.play(61);
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card2Pos, this);
+
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ if (scene->_cardsAvailableNumb < 0)
+ scene->_stockPile.remove();
+ } else
+ signal();
+ break;
+ case 2:
+ if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card2Pos.x)
+ && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card2Pos.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.fixPriority(170);
+ }
+
+ if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]);
+
+ scene->_animatedCard._card.hide();
+ if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._cardId == 0)
+ && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
+ if (scene->_cardsAvailableNumb < 0)
+ scene->shuffleCards();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95));
+ scene->_animatedCard._card.show();
+
+ scene->_aSound2.play(61);
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card3Pos, this);
+
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ if (scene->_cardsAvailableNumb < 0)
+ scene->_stockPile.remove();
+ } else
+ signal();
+ break;
+ case 3:
+ if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card3Pos.x)
+ && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card3Pos.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.fixPriority(170);
+ }
+
+ if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]);
+
+ scene->_animatedCard._card.hide();
+ if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._cardId == 0)
+ && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
+ if (scene->_cardsAvailableNumb < 0)
+ scene->shuffleCards();
+ scene->_animatedCard._card.setPosition(Common::Point(162, 95));
+ scene->_animatedCard._card.show();
+
+ scene->_aSound2.play(61);
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card4Pos, this);
+
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
+ scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
+ scene->_cardsAvailableNumb--;
+ if (scene->_cardsAvailableNumb < 0)
+ scene->_stockPile.remove();
+ } else
+ signal();
+ break;
+ case 4:
+ if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card4Pos.x)
+ && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card4Pos.y) ) {
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.postInit();
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card._moveDiff = Common::Point(30, 30);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setVisage(1332);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._stationPos, 0);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setStrip(1);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
+ scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.fixPriority(170);
+ }
+
+ if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
+ scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]);
+
+ scene->_animatedCard._card.hide();
+ switch (scene->_currentPlayerNumb) {
+ case 0:
+ scene->handlePlayer0();
+ break;
+ case 1:
+ scene->handlePlayer1();
+ break;
+ case 2:
+ scene->handleAutoplayPlayer2();
+ break;
+ case 3:
+ scene->handlePlayer3();
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Animations for discarding a card
+ */
+void Scene1337::Action5::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard1->_cardId;
+ scene->_currentDiscardIndex--;
+ if (!g_globals->_sceneObjects->contains(&scene->_discardPile._card)) {
+ // The first discarded card makes the pile appear
+ scene->_discardPile._card.postInit();
+ scene->_discardPile._card.hide();
+ scene->_discardPile._card.setVisage(1332);
+ scene->_discardPile._card.setPosition(scene->_discardPile._stationPos, 0);
+ scene->_discardPile._card.fixPriority(170);
+ }
+
+ scene->_discardPile._cardId = scene->_actionCard1->_cardId;
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+
+ if (scene->_actionCard1 == &scene->_selectedCard) {
+ scene->setCursorData(5, 1, 4);
+ scene->subC4CEC();
+ }
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+ Common::Point pt(128, 95);
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &pt, this);
+ }
+ break;
+ case 1:
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(&scene->_discardPile);
+ scene->_aSound2.play(61);
+ scene->handleNextTurn();
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Animations for playing a platform card
+ */
+void Scene1337::Action6::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_actionCard2->_cardId = 1;
+ scene->_actionCard2->_card.postInit();
+ scene->_actionCard2->_card.hide();
+ scene->_actionCard2->_card.setVisage(1332);
+ scene->_actionCard2->_card.setPosition(scene->_actionCard2->_stationPos);
+ scene->_actionCard2->_card.fixPriority(170);
+
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 1:
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(59);
+ if (scene->_actionCard1 == &scene->_selectedCard) {
+ scene->setCursorData(5, 1, 4);
+ scene->subC4CEC();
+ }
+ scene->handleNextTurn();
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Upgrade platform to station by playing a station card on top of it
+ */
+void Scene1337::Action7::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
+
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 1:
+ if (scene->_actionCard1 == &scene->_selectedCard) {
+ scene->setCursorData(5, 1, 4);
+ scene->subC4CEC();
+ }
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(59);
+ scene->_discardedPlatformCard._cardId = 1;
+ scene->_discardedPlatformCard._stationPos = scene->_actionCard2->_stationPos;
+ scene->_discardedPlatformCard._card.postInit();
+ scene->_discardedPlatformCard._card.hide();
+ scene->_discardedPlatformCard._card._flags = OBJFLAG_HIDING;
+
+ scene->discardCard(&scene->_discardedPlatformCard);
+ break;
+ default:
+ break;
+ }
+}
+
+// Remove a delay card
+void Scene1337::Action8::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
+ scene->_currentDiscardIndex--;
+
+ scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
+ scene->_actionCard1->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 1:
+ scene->_animatedCard._card.hide();
+
+ if (scene->_actionCard1 == &scene->_selectedCard) {
+ scene->setCursorData(5, 1, 4);
+ scene->subC4CEC();
+ }
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(58);
+ scene->discardCard(scene->_actionCard2);
+ break;
+ default:
+ break;
+ }
+}
+
+// Play delay card
+void Scene1337::Action9::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
+ scene->_actionCard2->_card.postInit();
+ scene->_actionCard2->_card.hide();
+ scene->_actionCard2->_card.setVisage(1332);
+ scene->_actionCard2->_card.setPosition(scene->_actionCard2->_stationPos, 0);
+ scene->_actionCard2->_card.fixPriority(170);
+
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 1:
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(57);
+
+ if (scene->_actionCard1 == &scene->_selectedCard) {
+ scene->setCursorData(5, 1, 4);
+ scene->subC4CEC();
+ }
+
+ scene->handleNextTurn();
+ break;
+ default:
+ break;
+ }
+}
+
+// Play a card on the central outpost.
+// This card is either a counter-trick card or a meteor card
+void Scene1337::Action10::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_actionCard3->_card.postInit();
+ scene->_actionCard3->_card.hide();
+ scene->_actionCard3->_card.setVisage(1332);
+ scene->_actionCard3->_card.setPosition(scene->_actionCard3->_stationPos, 0);
+ scene->_actionCard3->_card.fixPriority(170);
+ scene->_actionCard3->_cardId = scene->_actionCard1->_cardId;
+
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+
+ if (scene->_actionCard1 == &scene->_selectedCard) {
+ scene->setCursorData(5, 1, 4);
+ scene->subC4CEC();
+ }
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard3->_stationPos, this);
+ }
+ break;
+ case 1: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(scene->_actionCard3);
+ scene->_aSound1.play(57);
+
+ bool found = false;
+ int indexFound = -1;
+
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ for (indexFound = 0; indexFound < 3; indexFound++) {
+ // Check for the presence of an interceptor card
+ if (scene->_gameBoardSide[0]._handCard[indexFound]._cardId == 29) {
+ found = true;
+ break;
+ }
+ }
+ break;
+ case 1:
+ for (indexFound = 0; indexFound < 3; indexFound++) {
+ // Check for the presence of an interceptor card
+ if (scene->_gameBoardSide[1]._handCard[indexFound]._cardId == 29) {
+ found = true;
+ break;
+ }
+ }
+ break;
+ case 2:
+ for (indexFound = 0; indexFound < 3; indexFound++) {
+ // Check for the presence of an interceptor card
+ if (scene->_gameBoardSide[2]._handCard[indexFound]._cardId == 29) {
+ found = true;
+ break;
+ }
+ }
+ break;
+ case 3:
+ for (indexFound = 0; indexFound < 3; indexFound++) {
+ // Check for the presence of an interceptor card
+ if (scene->_gameBoardSide[3]._handCard[indexFound]._cardId == 29) {
+ found = true;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ bool found2 = false;
+
+ if (found) {
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ scene->playInterceptorCard(&scene->_gameBoardSide[0]._handCard[indexFound], scene->_actionCard3);
+ found2 = true;
+ break;
+ case 1:
+ scene->playInterceptorCard(&scene->_gameBoardSide[1]._handCard[indexFound], scene->_actionCard3);
+ found2 = true;
+ break;
+ case 2:
+ scene->subC4CD2();
+ if (MessageDialog::show(USE_INTERCEPTOR, NO_MSG, YES_MSG) == 0)
+ scene->subC4CEC();
+ else {
+ scene->playInterceptorCard(&scene->_gameBoardSide[2]._handCard[indexFound], scene->_actionCard3);
+ found2 = true;
+ }
+ break;
+ case 3:
+ scene->playInterceptorCard(&scene->_gameBoardSide[3]._handCard[indexFound], scene->_actionCard3);
+ found2 = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (found2)
+ break;
+
+ if (scene->_actionPlayerIdx == 2) {
+ int stationCount = 0;
+ for (int i = 0; i <= 7; i++) {
+ if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)
+ ++stationCount;
+ }
+
+ if (stationCount <= 1) {
+ for (int i = 0; i <= 7; i++) {
+ if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0) {
+ scene->_actionCard2 = &scene->_gameBoardSide[2]._outpostStation[i];
+ break;
+ }
+ }
+ } else {
+ scene->subC4CD2();
+
+ found2 = false;
+ while (!found2) {
+ scene->actionDisplay(1330, 130, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ // Wait for a mouse or keypress
+ Event event;
+ while (!g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !g_vm->shouldQuit()) {
+ g_globals->_scenePalette.signalListeners();
+ R2_GLOBALS._sceneObjects->draw();
+ g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
+ }
+
+ scene->_selectedCard._stationPos = event.mousePos;
+
+ for (int i = 0; i <= 7; i++) {
+ if (scene->_gameBoardSide[2]._outpostStation[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)) {
+ scene->_actionCard2 = &scene->_gameBoardSide[2]._outpostStation[i];
+ found2 = true;
+ break;
+ }
+ }
+ }
+ scene->subC4CEC();
+ }
+ }
+
+ scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
+ scene->_currentDiscardIndex--;
+ scene->_actionCard2->_cardId = 0;
+ scene->_actionCard2->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard2->_stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard3->_stationPos, this);
+ }
+ break;
+ case 2:
+ scene->_animatedCard._card.hide();
+ scene->discardCard(scene->_actionCard3);
+ break;
+ default:
+ break;
+ }
+}
+
+// Use Thief card (#25) and pick a card from the opponent
+void Scene1337::Action11::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_actionCard2->_card.postInit();
+ scene->_actionCard2->_card.hide();
+ scene->_actionCard2->_card.setVisage(1332);
+ scene->_actionCard2->_card.setPosition(scene->_actionCard2->_stationPos, 0);
+ scene->_actionCard2->_card.fixPriority(170);
+ scene->_actionCard2->_cardId = 25;
+
+ if (scene->_actionPlayerIdx == 2) {
+ scene->_animatedCard._card.setPosition(scene->_actionCard2->_stationPos, 0);
+ scene->setCursorData(5, 1, 4);
+ } else {
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ }
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 1: {
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(57);
+
+ bool found = false;
+ bool noAction = true;
+
+ int i = -1;
+
+ switch (scene->_actionVictimIdx) {
+ case 0:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[0]._handCard[i]._cardId == 27) {
+ found = true;
+ break;
+ }
+ }
+
+ if ((found) && (scene->getRandomCardFromHand(scene->_actionPlayerIdx) != -1)) {
+ scene->_actionCard1 = &scene->_gameBoardSide[0]._handCard[i];
+ scene->_actionCard2 = &scene->_gameBoardSide[0]._emptyStationPos;
+ if (scene->_actionPlayerIdx != 0) {
+ int tmpVal = scene->getRandomCardFromHand(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
+ }
+ scene->_actionItem.setAction(&scene->_action12);
+ noAction = false;
+ }
+ break;
+ case 1:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[1]._handCard[i]._cardId == 27) {
+ found = true;
+ break;
+ }
+ }
+
+ if ((found) && (scene->getRandomCardFromHand(scene->_actionPlayerIdx) != -1)) {
+ scene->_actionCard1 = &scene->_gameBoardSide[1]._handCard[i];
+ scene->_actionCard2 = &scene->_gameBoardSide[1]._emptyStationPos;
+ if (scene->_actionPlayerIdx != 1) {
+ int tmpVal = scene->getRandomCardFromHand(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
+ }
+ scene->_actionItem.setAction(&scene->_action12);
+ noAction = false;
+ }
+ break;
+ case 2:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[2]._handCard[i]._cardId == 27) {
+ found = true;
+ break;
+ }
+ }
+
+ if ((found) && (scene->getRandomCardFromHand(scene->_actionPlayerIdx) != -1)) {
+ scene->subC4CD2();
+ if (MessageDialog::show(USE_DOUBLE_AGENT, NO_MSG, YES_MSG) == 0)
+ scene->subC4CEC();
+ else {
+ scene->subC4CEC();
+ scene->_actionCard1 = &scene->_gameBoardSide[2]._handCard[i];
+ scene->_actionCard2 = &scene->_gameBoardSide[2]._emptyStationPos;
+ if (scene->_actionPlayerIdx != 2) {
+ int tmpVal = scene->getRandomCardFromHand(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
+ }
+ scene->_actionItem.setAction(&scene->_action12);
+ noAction = false;
+ }
+ }
+ break;
+ case 3:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[3]._handCard[i]._cardId == 27) {
+ found = true;
+ break;
+ }
+ }
+
+ if ((found) && (scene->getRandomCardFromHand(scene->_actionPlayerIdx) != -1)) {
+ scene->_actionCard1 = &scene->_gameBoardSide[3]._handCard[i];
+ scene->_actionCard2 = &scene->_gameBoardSide[3]._emptyStationPos;
+ if (scene->_actionPlayerIdx != 3) {
+ int tmpVal = scene->getRandomCardFromHand(scene->_actionPlayerIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionPlayerIdx]._handCard[tmpVal];
+ }
+ scene->_actionItem.setAction(&scene->_action12);
+ noAction = false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!noAction)
+ break;
+
+ if (scene->_actionPlayerIdx == 2) {
+ int count = 0;
+ if (scene->_actionVictimIdx != 2) {
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i]._cardId != 0)
+ ++count;
+ }
+ }
+
+ if (count > 1) {
+ scene->subC4CD2();
+
+ found = false;
+ while (!found) {
+ switch (scene->_actionVictimIdx) {
+ case 0:
+ scene->actionDisplay(1330, 131, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 1:
+ scene->actionDisplay(1330, 132, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 3:
+ scene->actionDisplay(1330, 133, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+
+ Event event;
+ while (!g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !g_vm->shouldQuit()) {
+ g_globals->_scenePalette.signalListeners();
+ R2_GLOBALS._sceneObjects->draw();
+ g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
+ }
+
+ scene->_selectedCard._stationPos = event.mousePos;
+
+ found = false;
+
+ if (scene->_actionVictimIdx != 2) {
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i]._cardId != 0)) {
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[i];
+ found = true;
+ break;
+ }
+ }
+ }
+ } // while
+ scene->_displayHelpFl = true;
+ scene->subC4CEC();
+ } else if (scene->_actionVictimIdx != 2) {
+ int tmpVal = scene->getRandomCardFromHand(scene->_actionVictimIdx);
+ scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionVictimIdx]._handCard[tmpVal];
+ }
+ }
+
+ scene->_actionCard1->_card.postInit();
+ scene->_actionCard1->_card.hide();
+ scene->_actionCard1->_card.setVisage(1332);
+ scene->_actionCard1->_card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_actionCard1->_card.fixPriority(170);
+ scene->_actionCard1->_card.setStrip2(1);
+ scene->_actionCard1->_cardId = scene->_actionCard3->_cardId;
+
+ scene->_actionCard3->_cardId = 0;
+ scene->_actionCard3->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard3->_stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard1->_stationPos, this);
+ }
+ break;
+ case 2:
+ scene->_animatedCard._card.hide();
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ scene->_actionCard1->_card.setFrame2(2);
+ scene->_actionCard1->_card.show();
+ break;
+ case 1:
+ scene->_actionCard1->_card.setFrame2(4);
+ scene->_actionCard1->_card.show();
+ break;
+ case 3:
+ scene->_actionCard1->_card.setFrame2(3);
+ scene->_actionCard1->_card.show();
+ break;
+ default:
+ scene->setAnimationInfo(scene->_actionCard1);
+ break;
+ }
+
+ scene->_currentPlayerNumb--;
+ scene->_showPlayerTurn = false;
+ scene->discardCard(scene->_actionCard2);
+ break;
+ default:
+ break;
+ }
+}
+
+// Pick a card in opponent hand
+void Scene1337::Action12::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0:
+ signal();
+ break;
+ case 1: {
+ scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
+ scene->_currentDiscardIndex++;
+ scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 2:
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(58);
+ if (scene->_actionVictimIdx == 2) {
+ int count = 0;
+ int i = -1;
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)
+ ++count;
+ }
+ break;
+ case 1:
+ for (i = 0; i <= 3; i++) {
+ // The original game was counting in the hand of player 3, which is obviously wrong
+ if (scene->_gameBoardSide[1]._handCard[i]._cardId != 0)
+ ++count;
+ }
+ break;
+ case 3:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)
+ ++count;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (count > 1) {
+ scene->subC4CD2();
+
+ bool found = false;
+
+ while (!found) {
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ scene->actionDisplay(1330, 131, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 1:
+ scene->actionDisplay(1330, 132, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 3:
+ scene->actionDisplay(1330, 133, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+
+ Event event;
+ while (!g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !g_vm->shouldQuit()) {
+ g_globals->_scenePalette.signalListeners();
+ R2_GLOBALS._sceneObjects->draw();
+ g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
+ }
+
+ scene->_selectedCard._stationPos = event.mousePos;
+
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[0]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)) {
+ found = true;
+ scene->_actionCard3 = &scene->_gameBoardSide[0]._handCard[i];
+ break;
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[1]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[1]._handCard[i]._cardId != 0)) {
+ found = true;
+ scene->_actionCard3 = &scene->_gameBoardSide[1]._handCard[i];
+ break;
+ }
+ }
+ break;
+ case 3:
+ for (i = 0; i <= 3; i++) {
+ if (scene->_gameBoardSide[3]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)) {
+ found = true;
+ scene->_actionCard3 = &scene->_gameBoardSide[3]._handCard[i];
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ scene->subC4CEC();
+ } else {
+ switch (scene->_actionPlayerIdx) {
+ case 0:
+ scene->_actionCard3 = &scene->_gameBoardSide[0]._handCard[scene->getRandomCardFromHand(0)];
+ break;
+ case 1:
+ scene->_actionCard3 = &scene->_gameBoardSide[1]._handCard[scene->getRandomCardFromHand(1)];
+ break;
+ case 3:
+ scene->_actionCard3 = &scene->_gameBoardSide[3]._handCard[scene->getRandomCardFromHand(3)];
+ break;
+ default:
+ break;
+ }
+ }
+
+ scene->_actionCard1->_card.postInit();
+ scene->_actionCard1->_card.hide();
+ scene->_actionCard1->_card.setVisage(1332);
+ scene->_actionCard1->_card.setPosition(scene->_actionCard1->_stationPos);
+ scene->_actionCard1->_card.fixPriority(170);
+ scene->_actionCard1->_card.setStrip2(1);
+ scene->_actionCard1->_cardId = scene->_actionCard3->_cardId;
+
+ scene->_actionCard3->_cardId = 0;
+ scene->_actionCard3->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard3->_stationPos);
+ scene->_animatedCard._card.show();
+ scene->_aSound1.play(57);
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard1->_stationPos, this);
+ }
+ break;
+ case 3:
+ scene->_animatedCard._card.hide();
+ switch (scene->_actionVictimIdx) {
+ case 0:
+ scene->_actionCard1->_card.setFrame2(2);
+ scene->_actionCard1->_card.show();
+ break;
+ case 1:
+ scene->_actionCard1->_card.setFrame2(4);
+ scene->_actionCard1->_card.show();
+ break;
+ case 3:
+ scene->_actionCard1->_card.setFrame2(3);
+ scene->_actionCard1->_card.show();
+ break;
+ default:
+ scene->setAnimationInfo(scene->_actionCard1);
+ break;
+ }
+ scene->discardCard(scene->_actionCard2);
+ break;
+ default:
+ break;
+ }
+}
+
+// Handle the animations of the interceptor card
+void Scene1337::Action13::signal() {
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_actionIndex++) {
+ case 0: {
+ scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
+ scene->_currentDiscardIndex--;
+
+ scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
+
+ scene->_actionCard1->_cardId = 0;
+ scene->_actionCard1->_card.remove();
+
+ scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
+ scene->_animatedCard._card.show();
+
+ NpcMover *mover = new NpcMover();
+ scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
+ }
+ break;
+ case 1:
+ scene->_animatedCard._card.hide();
+ scene->setAnimationInfo(scene->_actionCard2);
+ scene->_aSound1.play(58);
+ signal();
+ break;
+ case 2:
+ scene->discardCard(scene->_actionCard2);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene1337::postInit(SceneObjectList *OwnerList) {
+// In the original, may be found in subPostInit.
+// Without it, enableControl asserts
+ loadScene(1330);
+ R2_GLOBALS._uiElements._active = false;
+ SceneExt::postInit();
+//
+
+ // Hide the user interface
+ BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
+ R2_GLOBALS._uiElements._visible = false;
+
+ R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player._canWalk = false;
+ R2_GLOBALS._player._uiEnabled = false;
+
+ _delayedFunction = nullptr;
+
+ _actionCard1 = nullptr;
+ _actionCard2 = nullptr;
+ _actionCard3 = nullptr;
+
+ _gameBoardSide[2]._handCard[0]._stationPos = Common::Point(10, 174);
+ _gameBoardSide[2]._handCard[1]._stationPos = Common::Point(37, 174);
+ _gameBoardSide[2]._handCard[2]._stationPos = Common::Point(64, 174);
+ _gameBoardSide[2]._handCard[3]._stationPos = Common::Point(91, 174);
+
+ _gameBoardSide[2]._outpostStation[0]._stationPos = Common::Point(119, 174);
+ _gameBoardSide[2]._outpostStation[1]._stationPos = Common::Point(119, 148);
+ _gameBoardSide[2]._outpostStation[2]._stationPos = Common::Point(119, 122);
+ _gameBoardSide[2]._outpostStation[3]._stationPos = Common::Point(145, 122);
+ _gameBoardSide[2]._outpostStation[4]._stationPos = Common::Point(171, 122);
+ _gameBoardSide[2]._outpostStation[5]._stationPos = Common::Point(171, 148);
+ _gameBoardSide[2]._outpostStation[6]._stationPos = Common::Point(171, 174);
+ _gameBoardSide[2]._outpostStation[7]._stationPos = Common::Point(145, 174);
+
+ _gameBoardSide[2]._delayCard._stationPos = Common::Point(199, 174);
+
+ _gameBoardSide[2]._emptyStationPos._stationPos = Common::Point(145, 148);
+
+ _gameBoardSide[2]._card1Pos = Common::Point(10, 174);
+ _gameBoardSide[2]._card2Pos = Common::Point(37, 174);
+ _gameBoardSide[2]._card3Pos = Common::Point(64, 174);
+ _gameBoardSide[2]._card4Pos = Common::Point(91, 174);
+ _gameBoardSide[2]._frameNum = 2;
+
+ _gameBoardSide[3]._handCard[0]._stationPos = Common::Point(14, 14);
+ _gameBoardSide[3]._handCard[1]._stationPos = Common::Point(14, 36);
+ _gameBoardSide[3]._handCard[2]._stationPos = Common::Point(14, 58);
+ _gameBoardSide[3]._handCard[3]._stationPos = Common::Point(14, 80);
+
+ _gameBoardSide[3]._outpostStation[0]._stationPos = Common::Point(37, 66);
+ _gameBoardSide[3]._outpostStation[1]._stationPos = Common::Point(63, 66);
+ _gameBoardSide[3]._outpostStation[2]._stationPos = Common::Point(89, 66);
+ _gameBoardSide[3]._outpostStation[3]._stationPos = Common::Point(89, 92);
+ _gameBoardSide[3]._outpostStation[4]._stationPos = Common::Point(89, 118);
+ _gameBoardSide[3]._outpostStation[5]._stationPos = Common::Point(63, 118);
+ _gameBoardSide[3]._outpostStation[6]._stationPos = Common::Point(37, 118);
+ _gameBoardSide[3]._outpostStation[7]._stationPos = Common::Point(37, 92);
+
+ _gameBoardSide[3]._delayCard._stationPos = Common::Point(37, 145);
+
+ _gameBoardSide[3]._emptyStationPos._stationPos = Common::Point(63, 92);
+
+ _gameBoardSide[3]._card1Pos = Common::Point(14, 14);
+ _gameBoardSide[3]._card2Pos = Common::Point(14, 36);
+ _gameBoardSide[3]._card3Pos = Common::Point(14, 58);
+ _gameBoardSide[3]._card4Pos = Common::Point(14, 80);
+ _gameBoardSide[3]._frameNum = 3;
+
+ _gameBoardSide[0]._handCard[0]._stationPos = Common::Point(280, 5);
+ _gameBoardSide[0]._handCard[1]._stationPos = Common::Point(253, 5);
+ _gameBoardSide[0]._handCard[2]._stationPos = Common::Point(226, 5);
+ _gameBoardSide[0]._handCard[3]._stationPos = Common::Point(199, 5);
+
+ _gameBoardSide[0]._outpostStation[0]._stationPos = Common::Point(171, 16);
+ _gameBoardSide[0]._outpostStation[1]._stationPos = Common::Point(171, 42);
+ _gameBoardSide[0]._outpostStation[2]._stationPos = Common::Point(171, 68);
+ _gameBoardSide[0]._outpostStation[3]._stationPos = Common::Point(145, 68);
+ _gameBoardSide[0]._outpostStation[4]._stationPos = Common::Point(119, 68);
+ _gameBoardSide[0]._outpostStation[5]._stationPos = Common::Point(119, 42);
+ _gameBoardSide[0]._outpostStation[6]._stationPos = Common::Point(119, 16);
+ _gameBoardSide[0]._outpostStation[7]._stationPos = Common::Point(145, 16);
+
+ _gameBoardSide[0]._delayCard._stationPos = Common::Point(91, 16);
+
+ _gameBoardSide[0]._emptyStationPos._stationPos = Common::Point(145, 42);
+
+ _gameBoardSide[0]._card1Pos = Common::Point(280, 5);
+ _gameBoardSide[0]._card2Pos = Common::Point(253, 5);
+ _gameBoardSide[0]._card3Pos = Common::Point(226, 5);
+ _gameBoardSide[0]._card4Pos = Common::Point(199, 5);
+ _gameBoardSide[0]._frameNum = 2;
+
+ _gameBoardSide[1]._handCard[0]._stationPos = Common::Point(283, 146);
+ _gameBoardSide[1]._handCard[1]._stationPos = Common::Point(283, 124);
+ _gameBoardSide[1]._handCard[2]._stationPos = Common::Point(283, 102);
+ _gameBoardSide[1]._handCard[3]._stationPos = Common::Point(283, 80);
+
+ _gameBoardSide[1]._outpostStation[0]._stationPos = Common::Point(253, 122);
+ _gameBoardSide[1]._outpostStation[1]._stationPos = Common::Point(227, 122);
+ _gameBoardSide[1]._outpostStation[2]._stationPos = Common::Point(201, 122);
+ _gameBoardSide[1]._outpostStation[3]._stationPos = Common::Point(201, 96);
+ _gameBoardSide[1]._outpostStation[4]._stationPos = Common::Point(201, 70);
+ _gameBoardSide[1]._outpostStation[5]._stationPos = Common::Point(227, 70);
+ _gameBoardSide[1]._outpostStation[6]._stationPos = Common::Point(253, 70);
+ _gameBoardSide[1]._outpostStation[7]._stationPos = Common::Point(253, 96);
+
+ _gameBoardSide[1]._delayCard._stationPos = Common::Point(253, 43);
+
+ _gameBoardSide[1]._emptyStationPos._stationPos = Common::Point(227, 96);
+
+ _gameBoardSide[1]._card1Pos = Common::Point(283, 146);
+ _gameBoardSide[1]._card2Pos = Common::Point(283, 124);
+ _gameBoardSide[1]._card3Pos = Common::Point(283, 102);
+ _gameBoardSide[1]._card4Pos = Common::Point(283, 80);
+ _gameBoardSide[1]._frameNum = 4;
+
+ subPostInit();
+
+ _stockPile.postInit();
+}
+
+void Scene1337::remove() {
+ if (R2_GLOBALS._v57709 > 1) {
+ subD1917();
+ subD1940(false);
+ }
+
+ R2_GLOBALS._uiElements._active = true;
+ R2_GLOBALS._uiElements._visible = true;
+ SceneExt::remove();
+}
+
+void Scene1337::process(Event &event) {
+ if (event.eventType == EVENT_BUTTON_DOWN) {
+ if (event.btnState == BTNSHIFT_RIGHT) {
+ updateCursorId(R2_GLOBALS._mouseCursorId, true);
+ event.handled = true;
+ } else if (_delayedFunction) {
+ FunctionPtrType tmpFctPtr = _delayedFunction;
+ _delayedFunction = nullptr;
+ (this->*tmpFctPtr)();
+ event.handled = true;
+ }
+ } else if (event.eventType == EVENT_KEYPRESS) {
+ if (event.kbd.keycode == Common::KEYCODE_SPACE) {
+ if (_delayedFunction) {
+ FunctionPtrType tmpFctPtr = _delayedFunction;
+ _delayedFunction = nullptr;
+ (this->*tmpFctPtr)();
+ event.handled = true;
+ }
+ } else
+ warning("Fixme: Find proper keycode value");
+ }
+
+ if (!event.handled)
+ Scene::process(event);
+}
+
+void Scene1337::dispatch() {
+ if (!_instructionsDisplayedFl) {
+ ++_instructionsWaitCount;
+ if (_instructionsWaitCount == 4) {
+ _instructionsDisplayedFl = true;
+ suggestInstructions();
+ }
+ }
+
+ // The following code is in the original in sceneHandler::process(),
+ // which is terrible as it's checked in every scene of the game.
+ setCursorData(5, _cursorCurStrip, _cursorCurFrame);
+ //
+
+ Scene::dispatch();
+}
+
+void Scene1337::actionDisplay(int resNum, int lineNum, int x, int y, int keepOnScreen, int width, int textMode, int fontNum, int colFG, int colBGExt, int colFGExt) {
+ // TODO: Check if it's normal that arg5 is unused and replaced by an hardcoded 0 value
+ // May hide an original bug
+
+ SceneItem::display(resNum, lineNum, SET_X, x, SET_Y, y, SET_KEEP_ONSCREEN, 0,
+ SET_WIDTH, width, SET_POS_MODE, -1, SET_TEXT_MODE, textMode,
+ SET_FONT, fontNum, SET_FG_COLOR, colFG, SET_EXT_BGCOLOR, colBGExt,
+ SET_EXT_FGCOLOR, colFGExt, LIST_END);
+}
+
+void Scene1337::setAnimationInfo(Card *card) {
+ if (!card)
+ return;
+
+ if (card->_cardId > 25) {
+ card->_card.setStrip2(4);
+ card->_card.setFrame(card->_cardId - 25);
+ } else if (card->_cardId > 9) {
+ card->_card.setStrip2(3);
+ card->_card.setFrame(card->_cardId - 9);
+ } else {
+ card->_card.setStrip2(2);
+ card->_card.setFrame(card->_cardId);
+ }
+
+ card->_card.show();
+ R2_GLOBALS._sceneObjects->draw();
+}
+
+void Scene1337::handleNextTurn() {
+ switch (_winnerId) {
+ case -1:
+ ++_currentPlayerNumb;
+ if (_currentPlayerNumb > 3)
+ _currentPlayerNumb = 0;
+
+ if (_showPlayerTurn) {
+ _currentPlayerArrow.show();
+ switch (_currentPlayerNumb) {
+ case 0:
+ _currentPlayerArrow.setStrip(3);
+ break;
+ case 1:
+ _currentPlayerArrow.setStrip(4);
+ break;
+ case 2:
+ subD1975(174, 107);
+ _currentPlayerArrow.setStrip(1);
+ break;
+ case 3:
+ subC4CEC();
+ _currentPlayerArrow.setStrip(2);
+ break;
+ default:
+ break;
+ }
+
+ if (!_autoplay)
+ _delayedFunction = &Scene1337::handlePlayerTurn;
+ else
+ handlePlayerTurn();
+ } else {
+ handlePlayerTurn();
+ }
+ break;
+ case 0:
+ _aSound2.play(62);
+ actionDisplay(1330, 135, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ actionDisplay(1330, 121, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ actionDisplay(1330, 122, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ R2_GLOBALS._sceneObjects->draw();
+ actionDisplay(1330, 123, 159, 134, 1, 200, 0, 7, 0, 105, 105);
+ break;
+ case 1:
+ _aSound2.play(62);
+ actionDisplay(1330, 151, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ actionDisplay(1330, 118, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ actionDisplay(1330, 119, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ R2_GLOBALS._sceneObjects->draw();
+ actionDisplay(1330, 120, 159, 134, 1, 200, 0, 7, 0, 105, 105);
+ break;
+ case 2:
+ _aSound2.play(62);
+ actionDisplay(1330, 134, 159, 134, 1, 200, 0, 7, 0, 105, 105);
+ actionDisplay(1330, 124, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ actionDisplay(1330, 126, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ R2_GLOBALS._sceneObjects->draw();
+ actionDisplay(1330, 125, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ break;
+ case 3:
+ _aSound2.play(62);
+ actionDisplay(1330, 150, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ actionDisplay(1330, 115, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ actionDisplay(1330, 116, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ R2_GLOBALS._sceneObjects->draw();
+ actionDisplay(1330, 117, 159, 134, 1, 200, 0, 7, 0, 105, 105);
+ break;
+ default:
+ break;
+ }
+
+ if (_winnerId != -1)
+ R2_GLOBALS._sceneManager.changeScene(125);
+
+}
+
+void Scene1337::handlePlayerTurn() {
+ if (_showPlayerTurn)
+ _currentPlayerArrow.hide();
+
+ switch (_currentPlayerNumb) {
+ case 2:
+ subC4CD2();
+ if (_displayHelpFl)
+ actionDisplay(1330, 114, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ _displayHelpFl = false;
+ // No break on purpose
+ case 0:
+ // No break on purpose
+ case 1:
+ // No break on purpose
+ case 3:
+ _actionItem.setAction(&_action4);
+ default:
+ break;
+ }
+
+ _showPlayerTurn = true;
+
+}
+
+bool Scene1337::isStationCard(int cardId) {
+ switch (cardId) {
+ case 10:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 17:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 21:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Scene1337::isStopConstructionCard(int cardId) {
+ switch (cardId) {
+ case 11:
+ // No break on purpose
+ case 14:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 24:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int Scene1337::getStationId(int playerId, int handCardId) {
+ if ((_gameBoardSide[playerId]._handCard[handCardId]._cardId > 1) && (_gameBoardSide[playerId]._handCard[handCardId]._cardId <= 9))
+ return handCardId;
+
+ return -1;
+}
+
+int Scene1337::findPlatformCardInHand(int playerId) {
+ for (int i = 0; i <= 3; i++) {
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 1)
+ return i;
+ }
+
+ return -1;
+}
+
+int Scene1337::findMeteorCardInHand(int playerId) {
+ for (int i = 0; i <= 3; i++) {
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 13)
+ return i;
+ }
+
+ return -1;
+}
+
+int Scene1337::findThieftCardInHand(int playerId) {
+ for (int i = 0; i <= 3; i++) {
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 25)
+ return i;
+ }
+
+ return -1;
+}
+
+int Scene1337::isDelayCard(int cardId) {
+ switch (cardId) {
+ case 11:
+ // No break on purpose
+ case 14:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 24:
+ return cardId;
+ break;
+ default:
+ return -1;
+ break;
+ }
+}
+
+int Scene1337::getStationCardId(int cardId) {
+ switch (cardId) {
+ case 10:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 17:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 21:
+ return cardId;
+ default:
+ return -1;
+ }
+}
+
+void Scene1337::handlePlayer01Discard(int playerId) {
+ switch (playerId) {
+ case 0:
+ for (int i = 0; i <= 3; i++) {
+ if (getStationCardId(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if (isDelayCard(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Outpost Card
+ if ((_gameBoardSide[playerId]._handCard[i]._cardId > 1) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 9)) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if ((_gameBoardSide[playerId]._handCard[i]._cardId >= 26) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 33)) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Station Card
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 1) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Thief card
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 25) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Meteor Card
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 13) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+ break;
+ case 1:
+ for (int i = 0; i <= 3; i++) {
+ if ((_gameBoardSide[playerId]._handCard[i]._cardId >= 26) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 33)) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Station Card
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 1) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Outpost Card
+ if ((_gameBoardSide[playerId]._handCard[i]._cardId > 1) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 9)) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if (getStationCardId(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if (isDelayCard(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Thief card
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 25) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ // Meteor Card
+ if (_gameBoardSide[playerId]._handCard[i]._cardId == 13) {
+ discardCard(&_gameBoardSide[playerId]._handCard[i]);
+ return;
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene1337::playThieftCard(int playerId, Card *card, int victimId) {
+ _actionPlayerIdx = playerId;
+ _actionVictimIdx = victimId;
+
+ int randIndx;
+
+ for (;;) {
+ randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
+ if (_gameBoardSide[victimId]._handCard[randIndx]._cardId != 0)
+ break;
+ }
+
+ _actionCard1 = card;
+ _actionCard2 = &_gameBoardSide[victimId]._emptyStationPos;
+ _actionCard3 = &_gameBoardSide[victimId]._handCard[randIndx];
+
+ _actionItem.setAction(&_action11);
+}
+
+int Scene1337::getPreventionCardId(int cardId) {
+ int retVal;
+
+ switch (cardId) {
+ case 10:
+ retVal = 2;
+ break;
+ case 12:
+ retVal = 3;
+ break;
+ case 15:
+ retVal = 5;
+ break;
+ case 17:
+ retVal = 9;
+ break;
+ case 18:
+ retVal = 6;
+ break;
+ case 19:
+ retVal = 4;
+ break;
+ case 20:
+ retVal = 8;
+ break;
+ case 21:
+ retVal = 7;
+ break;
+ default:
+ retVal = -1;
+ }
+
+ return retVal;
+}
+
+bool Scene1337::isAttackPossible(int victimId, int cardId) {
+ if (victimId < 0 || victimId >= ARRAYSIZE(_gameBoardSide))
+ error("Scene1337::isAttackPossible() victimId:%d out of range 0 to %d", victimId, ARRAYSIZE(_gameBoardSide)-1);
+
+ for (int i = 0; i <= 7; i++) {
+ if (_gameBoardSide[victimId]._outpostStation[i]._cardId != 0) {
+ if (getPreventionCardId(cardId) == _gameBoardSide[victimId]._outpostStation[i]._cardId)
+ return false;
+ }
+ }
+ return true;
+}
+
+int Scene1337::getPlayerWithOutpost(int playerId) {
+ int randPlayerId = R2_GLOBALS._randomSource.getRandomNumber(3);
+
+ for (int i = 0; i <= 3; i++) {
+ if (randPlayerId != playerId) {
+ for (int j = 0; j <= 7; j++) {
+ if (_gameBoardSide[randPlayerId]._outpostStation[j]._cardId != 0)
+ return randPlayerId;
+ }
+ }
+
+ if (playerId == 1) {
+ randPlayerId--;
+ if (randPlayerId < 0)
+ randPlayerId = 3;
+ } else {
+ ++randPlayerId;
+ if (randPlayerId > 3)
+ randPlayerId = 0;
+ }
+ }
+
+ return -1;
+}
+
+bool Scene1337::checkAntiDelayCard(int delayCardId, int cardId) {
+ if ((delayCardId == 11) && (cardId == 26)) // Diplomacy
+ return true;
+
+ if ((delayCardId == 14) && (cardId == 30)) // Cure
+ return true;
+
+ if ((delayCardId == 16) && (cardId == 32)) // Agreement
+ return true;
+
+ if ((delayCardId == 24) && (cardId == 28)) // Innovation
+ return true;
+
+ return false;
+}
+
+void Scene1337::playStationCard(Card *station, Card *platform) {
+ _actionCard1 = station;
+ _actionCard2 = platform;
+ _actionItem.setAction(&_action7);
+}
+
+int Scene1337::getRandomCardFromHand(int playerId) {
+ if ( (_gameBoardSide[playerId]._handCard[0]._cardId == 0)
+ && (_gameBoardSide[playerId]._handCard[1]._cardId == 0)
+ && (_gameBoardSide[playerId]._handCard[2]._cardId == 0)
+ && (_gameBoardSide[playerId]._handCard[3]._cardId == 0))
+ return -1;
+
+ int randIndx;
+ for (;;) {
+ randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
+ if (_gameBoardSide[playerId]._handCard[randIndx]._cardId != 0)
+ break;
+ }
+
+ return randIndx;
+}
+
+void Scene1337::playPlatformCard(Card *card, Card *dest) {
+ _actionCard1 = card;
+ _actionCard2 = dest;
+
+ _actionItem.setAction(&_action6);
+}
+
+void Scene1337::playDelayCard(Card *card, Card *dest) {
+ _actionCard1 = card;
+ _actionCard2 = dest;
+
+ _actionItem.setAction(&_action9);
+}
+
+void Scene1337::playAntiDelayCard(Card *card, Card *dest) {
+ _actionCard1 = card;
+ _actionCard2 = dest;
+
+ _actionItem.setAction(&_action8);
+
+ // WORKAROUND: Restore the default cursor and for a call to signal.
+ // This works around the cursor caching we got rid of, and avoid
+ // the game ends in an eternal loop when a player reacts to another player
+ // attack.
+ setCursorData(5, 1, 4);
+ signal();
+}
+
+
+Scene1337::Card *Scene1337::getStationCard(int playerId) {
+ for (int i = 0; i <= 7; i++) {
+ if ((_gameBoardSide[playerId]._outpostStation[i]._cardId >= 1) && (_gameBoardSide[playerId]._outpostStation[i]._cardId <= 9))
+ return &_gameBoardSide[playerId]._outpostStation[i];
+ }
+
+ return nullptr;
+}
+
+void Scene1337::playCentralOutpostCard(Card *card, int playerId) {
+ _actionCard1 = card;
+ _actionCard2 = getStationCard(playerId);
+ _actionCard3 = &_gameBoardSide[playerId]._emptyStationPos;
+ _actionPlayerIdx = playerId;
+ _actionItem.setAction(&_action10);
+}
+
+void Scene1337::discardCard(Card *card) {
+ _actionCard1 = card;
+
+ _actionItem.setAction(&_action5);
+}
+
+void Scene1337::subC4CD2() {
+ if (R2_GLOBALS._v57709 > 0) {
+ subD1917();
+ subD1940(false); // _v5780C--
+ }
+}
+
+void Scene1337::subC4CEC() {
+ if (R2_GLOBALS._v57709 == 0) {
+ subD18F5();
+ subD1940(true); // _v5780C++
+ }
+}
+
+// Play Interceptor card
+void Scene1337::playInterceptorCard(Card *subObj1, Card *subObj2) {
+ _actionCard1 = subObj1;
+ _actionCard2 = subObj2;
+
+ _actionItem.setAction(&_action13);
+}
+
+void Scene1337::displayDialog(int dialogNumb) {
+ switch (dialogNumb - 1) {
+ case 0:
+ actionDisplay(1330, 53, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 1:
+ actionDisplay(1330, 57, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 2:
+ actionDisplay(1330, 58, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 3:
+ actionDisplay(1330, 59, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 4:
+ actionDisplay(1330, 60, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 5:
+ actionDisplay(1330, 61, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 6:
+ actionDisplay(1330, 62, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 7:
+ actionDisplay(1330, 63, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 8:
+ actionDisplay(1330, 64, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 9:
+ actionDisplay(1330, 65, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 10:
+ actionDisplay(1330, 67, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 11:
+ actionDisplay(1330, 69, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 12:
+ actionDisplay(1330, 71, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ actionDisplay(1330, 72, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ actionDisplay(1330, 73, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 13:
+ actionDisplay(1330, 79, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 14:
+ actionDisplay(1330, 81, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ actionDisplay(1330, 83, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 16:
+ actionDisplay(1330, 85, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 17:
+ actionDisplay(1330, 87, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 18:
+ actionDisplay(1330, 89, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 19:
+ actionDisplay(1330, 91, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ actionDisplay(1330, 93, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 23:
+ actionDisplay(1330, 95, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 24:
+ actionDisplay(1330, 97, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 25:
+ actionDisplay(1330, 104, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 26:
+ actionDisplay(1330, 105, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ actionDisplay(1330, 106, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 27:
+ actionDisplay(1330, 110, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 28:
+ actionDisplay(1330, 108, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ actionDisplay(1330, 109, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 29:
+ actionDisplay(1330, 111, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 31:
+ actionDisplay(1330, 112, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene1337::subPostInit() {
+ R2_GLOBALS._v57709 = 0;
+ R2_GLOBALS._v5780C = 0;
+ updateCursorId(1, false);
+ subD1940(true); // _v5780C++
+ subD18F5();
+
+// loadScene(1330);
+// SceneExt::postInit();
+
+ R2_GLOBALS._scenePalette.addRotation(224, 235, 1);
+
+ _availableCardsPile[0] = 1;
+ _availableCardsPile[1] = 1;
+ _availableCardsPile[2] = 1;
+ _availableCardsPile[3] = 1;
+ _availableCardsPile[4] = 1;
+ _availableCardsPile[5] = 1;
+ _availableCardsPile[6] = 1;
+ _availableCardsPile[7] = 1;
+ _availableCardsPile[8] = 26;
+ _availableCardsPile[9] = 2;
+ _availableCardsPile[10] = 2;
+ _availableCardsPile[11] = 2;
+ _availableCardsPile[12] = 2;
+ _availableCardsPile[13] = 2;
+ _availableCardsPile[14] = 26;
+ _availableCardsPile[15] = 3;
+ _availableCardsPile[16] = 3;
+ _availableCardsPile[17] = 3;
+ _availableCardsPile[18] = 3;
+ _availableCardsPile[19] = 3;
+ _availableCardsPile[20] = 28;
+ _availableCardsPile[21] = 4;
+ _availableCardsPile[22] = 4;
+ _availableCardsPile[23] = 4;
+ _availableCardsPile[24] = 4;
+ _availableCardsPile[25] = 4;
+ _availableCardsPile[26] = 28;
+ _availableCardsPile[27] = 5;
+ _availableCardsPile[28] = 5;
+ _availableCardsPile[29] = 5;
+ _availableCardsPile[30] = 5;
+ _availableCardsPile[31] = 5;
+ _availableCardsPile[32] = 30;
+ _availableCardsPile[33] = 6;
+ _availableCardsPile[34] = 6;
+ _availableCardsPile[35] = 6;
+ _availableCardsPile[36] = 6;
+ _availableCardsPile[37] = 6;
+ _availableCardsPile[38] = 30;
+ _availableCardsPile[39] = 7;
+ _availableCardsPile[40] = 7;
+ _availableCardsPile[41] = 7;
+ _availableCardsPile[42] = 7;
+ _availableCardsPile[43] = 7;
+ _availableCardsPile[44] = 32;
+ _availableCardsPile[45] = 8;
+ _availableCardsPile[46] = 8;
+ _availableCardsPile[47] = 8;
+ _availableCardsPile[48] = 8;
+ _availableCardsPile[49] = 8;
+ _availableCardsPile[50] = 32;
+ _availableCardsPile[51] = 9;
+ _availableCardsPile[52] = 9;
+ _availableCardsPile[53] = 9;
+ _availableCardsPile[54] = 9;
+ _availableCardsPile[55] = 9;
+ _availableCardsPile[56] = 10;
+ _availableCardsPile[57] = 11;
+ _availableCardsPile[58] = 12;
+ _availableCardsPile[59] = 13;
+ _availableCardsPile[60] = 13;
+ _availableCardsPile[61] = 14;
+ _availableCardsPile[62] = 15;
+ _availableCardsPile[63] = 16;
+ _availableCardsPile[64] = 17;
+ _availableCardsPile[65] = 18;
+ _availableCardsPile[66] = 19;
+ _availableCardsPile[67] = 20;
+ _availableCardsPile[68] = 21;
+ _availableCardsPile[69] = 26;
+ _availableCardsPile[70] = 28;
+ _availableCardsPile[71] = 24;
+ _availableCardsPile[72] = 25;
+ _availableCardsPile[73] = 25;
+ _availableCardsPile[74] = 25;
+ _availableCardsPile[75] = 25;
+ _availableCardsPile[76] = 26;
+ _availableCardsPile[77] = 26;
+ _availableCardsPile[78] = 26;
+ _availableCardsPile[79] = 27;
+ _availableCardsPile[80] = 27;
+ _availableCardsPile[81] = 28;
+ _availableCardsPile[82] = 28;
+ _availableCardsPile[83] = 28;
+ _availableCardsPile[84] = 29;
+ _availableCardsPile[85] = 29;
+ _availableCardsPile[86] = 29;
+ _availableCardsPile[87] = 30;
+ _availableCardsPile[88] = 30;
+ _availableCardsPile[89] = 30;
+ _availableCardsPile[90] = 30;
+ _availableCardsPile[91] = 32;
+ _availableCardsPile[92] = 1;
+ _availableCardsPile[93] = 32;
+ _availableCardsPile[94] = 32;
+ _availableCardsPile[95] = 32;
+ _availableCardsPile[96] = 1;
+ _availableCardsPile[97] = 1;
+ _availableCardsPile[98] = 1;
+ _availableCardsPile[99] = 0;
+
+ _cardsAvailableNumb = 98;
+ _currentDiscardIndex = 98; // CHECKME: Would make more sense at pos 99
+
+ _discardPile._cardId = 0;
+ _discardPile._stationPos = Common::Point(128, 95);
+
+ _stockCard._cardId = 0;
+ _stockCard._stationPos = Common::Point(162, 95);
+
+ _selectedCard._cardId = 0;
+
+ _animatedCard._card.postInit();
+ _animatedCard._card.setVisage(1332);
+ _animatedCard._card.setStrip(5);
+ _animatedCard._card.setFrame(1);
+ _animatedCard._card._moveDiff = Common::Point(10, 10);
+ _animatedCard._card.fixPriority(400);
+ _animatedCard._card.setPosition(Common::Point(128, 95), 0);
+ _animatedCard._card.animate(ANIM_MODE_2, NULL);
+ _animatedCard._card.hide();
+
+ _currentPlayerArrow.postInit();
+ _currentPlayerArrow.setVisage(1334);
+ _currentPlayerArrow.setStrip(1);
+ _currentPlayerArrow.setFrame(1);
+ _currentPlayerArrow._numFrames = 12;
+ _currentPlayerArrow.fixPriority(500);
+ _currentPlayerArrow.setPosition(Common::Point(174, 107), 0);
+ _currentPlayerArrow.animate(ANIM_MODE_2, NULL);
+ _currentPlayerArrow.hide();
+
+ _showPlayerTurn = true;
+ _displayHelpFl = false;
+ _winnerId = -1;
+
+ _helpIcon.postInit();
+ _helpIcon.setup(9531, 1, 1);
+ _helpIcon.setPosition(Common::Point(249, 168));
+ _helpIcon.setPriority(155);
+ _helpIcon._effect = EFFECT_NONE;
+ _helpIcon.show();
+
+ _autoplay = false;
+ _instructionsDisplayedFl = false;
+ _instructionsWaitCount = 0;
+}
+
+void Scene1337::suggestInstructions() {
+ if (R2_GLOBALS._v57709 > 0)
+ subD1917();
+
+ if (MessageDialog::show(NEED_INSTRUCTIONS, NO_MSG, YES_MSG) == 0) {
+ if (R2_GLOBALS._v57709 == 0)
+ subD18F5();
+ dealCards();
+ } else {
+ if (R2_GLOBALS._v57709 == 0)
+ subD18F5();
+ displayInstructions();
+ }
+}
+
+void Scene1337::displayInstructions() {
+ _actionItem.setAction(&_action1);
+}
+
+void Scene1337::shuffleCards() {
+ R2_GLOBALS._sceneObjects->draw();
+
+ // Remove holes in card pile
+ for (int i = 0; i <= 98; i++) {
+ if (_availableCardsPile[i] == 0) {
+ for (int j = i + 1; j <= 98; j ++) {
+ if (_availableCardsPile[j] != 0) {
+ _availableCardsPile[i] = _availableCardsPile[j];
+ _availableCardsPile[j] = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ // Compute the number of available cards
+ for (int i = 0; i <= 99; i ++) {
+ if (_availableCardsPile[i] == 0) {
+ // CHECKME: This will fail if i == 0, which shouldn't happen
+ // as we don't shuffle cards when no card is available.
+ _cardsAvailableNumb = i - 1;
+ _currentDiscardIndex = 98; // CHECKME: Would make more sense at pos 99
+ break;
+ }
+ }
+
+ for (int i = 0; i < 2000; i ++) {
+ int randIndx = R2_GLOBALS._randomSource.getRandomNumber(_cardsAvailableNumb);
+ int swap = _availableCardsPile[0];
+ _availableCardsPile[0] = _availableCardsPile[randIndx];
+ _availableCardsPile[randIndx] = swap;
+ }
+
+ _shuffleEndedFl = false;
+
+ // Shuffle cards
+ _animatedCard._card.setAction(&_action2);
+
+ while(!_shuffleEndedFl && !g_vm->shouldQuit()) {
+ g_globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
+ g_globals->_scenePalette.signalListeners();
+ R2_GLOBALS._sceneObjects->draw();
+ g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
+ }
+}
+
+void Scene1337::dealCards() {
+ _animatedCard._card._moveDiff = Common::Point(30, 30);
+ shuffleCards();
+
+ // Deal cards
+ _actionItem.setAction(&_action3);
+}
+
+void Scene1337::showOptionsDialog() {
+ // Display menu with "Auto Play", "New Game", "Quit" and "Continue"
+ OptionsDialog::show();
+}
+
+void Scene1337::handleClick(int arg1, Common::Point pt) {
+ 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)
+ || _gameBoardSide[0]._outpostStation[i].isIn(pt)
+ || _gameBoardSide[1]._outpostStation[i].isIn(pt)
+ || _gameBoardSide[3]._outpostStation[i].isIn(pt) ) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ switch (curReg) {
+ case 5:
+ if (_gameBoardSide[2]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[2]._outpostStation[i]._cardId);
+ else
+ actionDisplay(1330, 20, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 10:
+ if (_gameBoardSide[3]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[3]._outpostStation[i]._cardId);
+ else
+ actionDisplay(1330, 22, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ if (_gameBoardSide[0]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[0]._outpostStation[i]._cardId);
+ else
+ actionDisplay(1330, 21, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ if (_gameBoardSide[1]._outpostStation[i]._cardId != 0)
+ displayDialog(_gameBoardSide[1]._outpostStation[i]._cardId);
+ else
+ actionDisplay(1330, 23, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ } else if ( _gameBoardSide[2]._delayCard.isIn(pt)
+ || _gameBoardSide[0]._delayCard.isIn(pt)
+ || _gameBoardSide[1]._delayCard.isIn(pt)
+ || _gameBoardSide[3]._delayCard.isIn(pt) ) {
+ switch (curReg) {
+ case 5:
+ if (_gameBoardSide[2]._delayCard._cardId != 0)
+ displayDialog(_gameBoardSide[2]._delayCard._cardId);
+ else
+ actionDisplay(1330, 10, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 10:
+ if (_gameBoardSide[3]._delayCard._cardId != 0)
+ displayDialog(_gameBoardSide[3]._delayCard._cardId);
+ else
+ actionDisplay(1330, 16, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ if (_gameBoardSide[0]._delayCard._cardId != 0)
+ displayDialog(_gameBoardSide[0]._delayCard._cardId);
+ else
+ actionDisplay(1330, 13, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ if (_gameBoardSide[1]._delayCard._cardId != 0)
+ displayDialog(_gameBoardSide[1]._delayCard._cardId);
+ else
+ actionDisplay(1330, 18, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ } else if (_discardPile.isIn(pt)) {
+ if (_discardPile._cardId != 0)
+ displayDialog(_discardPile._cardId);
+ else
+ actionDisplay(1330, 7, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (_helpIcon._bounds.contains(pt))
+ actionDisplay(1330, 43, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else if (_stockCard.isIn(pt))
+ actionDisplay(1330, 4, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else if ( (_gameBoardSide[2]._emptyStationPos.isIn(pt))
+ || (_gameBoardSide[3]._emptyStationPos.isIn(pt))
+ || (_gameBoardSide[0]._emptyStationPos.isIn(pt))
+ || (_gameBoardSide[1]._emptyStationPos.isIn(pt)) )
+ actionDisplay(1330, 32, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else if (_gameBoardSide[2]._handCard[0].isIn(pt))
+ displayDialog(_gameBoardSide[2]._handCard[0]._cardId);
+ else if (_gameBoardSide[2]._handCard[1].isIn(pt))
+ displayDialog(_gameBoardSide[2]._handCard[1]._cardId);
+ else if (_gameBoardSide[2]._handCard[2].isIn(pt))
+ displayDialog(_gameBoardSide[2]._handCard[2]._cardId);
+ else if (_gameBoardSide[2]._handCard[3].isIn(pt))
+ displayDialog(_gameBoardSide[2]._handCard[3]._cardId);
+ else if ((curReg >= 6) && (curReg <= 9))
+ actionDisplay(1330, 29, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else if ((curReg >= 11) && (curReg <= 14))
+ actionDisplay(1330, 31, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else if ((curReg >= 16) && (curReg <= 19))
+ actionDisplay(1330, 30, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else {
+ switch (curReg) {
+ case 0:
+ actionDisplay(1330, 2, 159, 134, 1, 200, 0, 7, 0, 105, 105);
+ break;
+ case 5:
+ actionDisplay(1330, 25, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 10:
+ actionDisplay(1330, 27, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ actionDisplay(1330, 26, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ actionDisplay(1330, 28, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 21:
+ actionDisplay(1330, 24, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (arg1 != 1)
+ return;
+
+ for (int i = 0; i <= 7; i++) {
+ if (_gameBoardSide[2]._outpostStation[i].isIn(pt)) {
+ switch (_gameBoardSide[2]._outpostStation[i]._cardId) {
+ case 0:
+ actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 1:
+ actionDisplay(1330, 54, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ actionDisplay(1330, 34, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ }
+ return;
+ }
+ if (_gameBoardSide[0]._outpostStation[i].isIn(pt)) {
+ switch (_gameBoardSide[0]._outpostStation[i]._cardId) {
+ case 0:
+ actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ }
+ return;
+ }
+ if (_gameBoardSide[1]._outpostStation[i].isIn(pt)) {
+ switch (_gameBoardSide[1]._outpostStation[i]._cardId) {
+ case 0:
+ actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ break;
+ default:
+ actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ break;
+ }
+ return;
+ }
+ if (_gameBoardSide[3]._outpostStation[i].isIn(pt)) {
+ switch (_gameBoardSide[3]._outpostStation[i]._cardId) {
+ case 0:
+ actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ break;
+ default:
+ actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ break;
+ }
+ return;
+ }
+ }
+
+ if (_gameBoardSide[2]._delayCard.isIn(pt)) {
+ // The original uses _gameBoardSide[0], which is obviously a bug.
+ if (_gameBoardSide[2]._delayCard._cardId != 0)
+ actionDisplay(1330, 39, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else
+ actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ return;
+ }
+ if (_gameBoardSide[3]._delayCard.isIn(pt)) {
+ if (_gameBoardSide[3]._delayCard._cardId != 0)
+ actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ else
+ actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+
+ return;
+ }
+ if (_gameBoardSide[1]._delayCard.isIn(pt)) {
+ if (_gameBoardSide[1]._delayCard._cardId != 0)
+ actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ else
+ actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+
+ return;
+ }
+ if (_gameBoardSide[0]._delayCard.isIn(pt)) {
+ if (_gameBoardSide[0]._delayCard._cardId != 0)
+ actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else
+ actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+
+ return;
+ }
+ if (_gameBoardSide[3]._emptyStationPos.isIn(pt)) {
+ actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ return;
+ }
+ if (_gameBoardSide[1]._emptyStationPos.isIn(pt)) {
+ actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ return;
+ }
+ if (_gameBoardSide[0]._emptyStationPos.isIn(pt)) {
+ actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ return;
+ }
+
+ if (_helpIcon._bounds.contains(pt)) {
+ showOptionsDialog();
+ return;
+ }
+
+ if (_discardPile.isIn(pt))
+ actionDisplay(1330, 9, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else if (_stockCard.isIn(pt))
+ actionDisplay(1330, 5, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ else {
+ switch (curReg) {
+ case 0:
+ actionDisplay(1330, 3, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 6:
+ // no break on purpose
+ case 7:
+ // no break on purpose
+ case 8:
+ // no break on purpose
+ case 9:
+ actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ break;
+ case 10:
+ actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
+ break;
+ case 11:
+ // no break on purpose
+ case 12:
+ // no break on purpose
+ case 13:
+ // no break on purpose
+ case 14:
+ actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 16:
+ // no break on purpose
+ case 17:
+ // no break on purpose
+ case 18:
+ // no break on purpose
+ case 19:
+ actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ break;
+ case 20:
+ actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
+ break;
+ default:
+ actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ }
+ }
+}
+
+void Scene1337::handlePlayer0() {
+ if (_gameBoardSide[0]._delayCard._cardId != 0) {
+ switch (_gameBoardSide[0]._delayCard._cardId) {
+ case 10:
+ //No break on purpose
+ case 12:
+ //No break on purpose
+ case 15:
+ //No break on purpose
+ case 17:
+ //No break on purpose
+ case 18:
+ //No break on purpose
+ case 19:
+ //No break on purpose
+ case 20:
+ //No break on purpose
+ case 21:
+ discardCard(&_gameBoardSide[0]._delayCard);
+ return;
+ default:
+ for (int i = 0; i <= 3; i++) {
+ if (checkAntiDelayCard(_gameBoardSide[0]._delayCard._cardId, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playAntiDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[0]._delayCard);
+ return;
+ }
+ }
+
+ break;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ int tmpVal = getStationId(0, i);
+
+ if (tmpVal != -1) {
+ bool stationAlreadyPresentFl = false;
+ for (int j = 0; j <= 7; j++) {
+ if (_gameBoardSide[0]._outpostStation[j]._cardId == _gameBoardSide[0]._handCard[tmpVal]._cardId) {
+ stationAlreadyPresentFl = true;
+ break;
+ }
+ }
+
+ if (!stationAlreadyPresentFl) {
+ for (int j = 0; j <= 7; j++) {
+ if ((_gameBoardSide[0]._outpostStation[j]._cardId == 1) && !isStopConstructionCard(_gameBoardSide[0]._delayCard._cardId)) {
+ int stationCount = 0;
+ for (int k = 0; k <= 7; k++) {
+ if ((_gameBoardSide[0]._outpostStation[k]._cardId > 1) && (_gameBoardSide[0]._outpostStation[k]._cardId <= 9)) {
+ ++stationCount;
+ }
+ }
+
+ if (stationCount == 7)
+ _winnerId = 0;
+
+ playStationCard(&_gameBoardSide[0]._handCard[tmpVal], &_gameBoardSide[0]._outpostStation[j]);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ int tmpVal = findPlatformCardInHand(0);
+
+ if (tmpVal != -1) {
+ for (int i = 0; i <= 7; i++) {
+ if ((_gameBoardSide[0]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[0]._delayCard._cardId)) {
+ playPlatformCard(&_gameBoardSide[0]._handCard[tmpVal], &_gameBoardSide[0]._outpostStation[i]);
+ return;
+ }
+ }
+ }
+
+ int meteorCardId = findMeteorCardInHand(0);
+ if (meteorCardId != -1) {
+ for (int i = 0; i <= 7; i++) {
+ if (_gameBoardSide[2]._outpostStation[i]._cardId != 0) {
+ playCentralOutpostCard(&_gameBoardSide[0]._handCard[meteorCardId], 2);
+ return;
+ }
+ }
+ }
+
+ int thieftId = findThieftCardInHand(0);
+ if (thieftId != -1) {
+ if ( (_gameBoardSide[2]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[2]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[2]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[2]._handCard[3]._cardId != 0) ) {
+ playThieftCard(0, &_gameBoardSide[0]._handCard[thieftId], 2);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if ((isDelayCard(_gameBoardSide[0]._handCard[i]._cardId) != -1)
+ && (_gameBoardSide[2]._delayCard._cardId == 0)
+ && isAttackPossible(2, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[2]._delayCard);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if ((getStationCardId(_gameBoardSide[0]._handCard[i]._cardId) != -1)
+ && (_gameBoardSide[2]._delayCard._cardId == 0)
+ && isAttackPossible(2, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[2]._delayCard);
+ return;
+ }
+ }
+
+ meteorCardId = findMeteorCardInHand(0);
+ int victimId = getPlayerWithOutpost(0);
+
+ if ((meteorCardId != -1) && (victimId != -1)) {
+ playCentralOutpostCard(&_gameBoardSide[0]._handCard[meteorCardId], victimId);
+ return;
+ }
+
+ thieftId = findThieftCardInHand(0);
+ if (thieftId != -1) {
+ if ( (_gameBoardSide[1]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[3]._cardId != 0) ) {
+ playThieftCard(0, &_gameBoardSide[0]._handCard[thieftId], 1);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ if (getStationCardId(_gameBoardSide[0]._handCard[i]._cardId) != -1) {
+ if ((_gameBoardSide[1]._delayCard._cardId == 0) && isAttackPossible(1, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[1]._delayCard);
+ return;
+ }
+
+ if ((_gameBoardSide[3]._delayCard._cardId == 0) && isAttackPossible(3, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[3]._delayCard);
+ return;
+ }
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ tmpVal = isDelayCard(_gameBoardSide[0]._handCard[i]._cardId);
+ if (tmpVal != -1) {
+ if ((_gameBoardSide[1]._delayCard._cardId == 0) && isAttackPossible(1, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[1]._delayCard);
+ return;
+ }
+
+ if ((_gameBoardSide[3]._delayCard._cardId == 0) && isAttackPossible(3, _gameBoardSide[0]._handCard[i]._cardId)) {
+ playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[3]._delayCard);
+ return;
+ }
+ }
+ }
+
+ handlePlayer01Discard(0);
+}
+
+void Scene1337::handlePlayer1() {
+ if (this->_gameBoardSide[1]._delayCard._cardId != 0) {
+ switch (_gameBoardSide[1]._delayCard._cardId) {
+ case 10:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 17:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 21:
+ discardCard(&_gameBoardSide[1]._delayCard);
+ return;
+ default:
+ for (int i = 0; i <= 3; i++) {
+ if (checkAntiDelayCard(_gameBoardSide[1]._delayCard._cardId, _gameBoardSide[1]._handCard[i]._cardId)) {
+ playAntiDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[1]._delayCard);
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ int tmpIndx = getStationId(1, i);
+ if (tmpIndx == -1)
+ break;
+
+ int tmpVal = 0;
+ for (int j = 0; j <= 7; j++) {
+ if (_gameBoardSide[1]._outpostStation[j]._cardId == _gameBoardSide[1]._handCard[tmpIndx]._cardId) {
+ tmpVal = 1;
+ break;
+ }
+ }
+
+ if (tmpVal == 0)
+ break;
+
+ for (int j = 0; j <= 7; j++) {
+ if ((_gameBoardSide[1]._outpostStation[j]._cardId == 1) && !isStopConstructionCard(_gameBoardSide[1]._delayCard._cardId)) {
+ int stationCount = 0;
+ for (int k = 0; k <= 7; k++) {
+ if ((_gameBoardSide[1]._outpostStation[k]._cardId > 1) && (_gameBoardSide[1]._outpostStation[k]._cardId <= 9))
+ ++stationCount;
+ }
+
+ if (stationCount == 7)
+ _winnerId = 1;
+
+ playStationCard(&_gameBoardSide[1]._handCard[tmpIndx], &_gameBoardSide[1]._outpostStation[j]);
+ return;
+ }
+ }
+ }
+
+ int normalCardId = findPlatformCardInHand(1);
+ if (normalCardId != -1) {
+ for (int i = 0; i <= 7; i++) {
+ if ((_gameBoardSide[1]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[1]._delayCard._cardId)) {
+ playPlatformCard(&_gameBoardSide[1]._handCard[normalCardId], &_gameBoardSide[1]._outpostStation[i]);
+ return;
+ }
+ }
+ }
+
+ int meterorCardId = findMeteorCardInHand(1);
+ int victimId = getPlayerWithOutpost(1);
+
+ if ((meterorCardId != -1) && (victimId != -1)) {
+ playCentralOutpostCard(&_gameBoardSide[1]._handCard[meterorCardId], victimId);
+ return;
+ }
+
+ int thieftId = findThieftCardInHand(1);
+ if (thieftId != -1) {
+ int playerIdFound = -1;
+ int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
+ for (int i = 0; i <= 3; i++) {
+ if (rndVal != 1) {
+ if ( (_gameBoardSide[rndVal]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[rndVal]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[rndVal]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[rndVal]._handCard[3]._cardId != 0)) {
+ playerIdFound = rndVal;
+ break;
+ }
+ }
+ // The original was only updating in the rndVal block,
+ // which was a bug as the checks were stopping at this point
+ rndVal--;
+ if (rndVal < 0)
+ rndVal = 3;
+ }
+
+ if (playerIdFound != -1) {
+ playThieftCard(1, &_gameBoardSide[1]._handCard[thieftId], playerIdFound);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 3; i++) {
+ int tmpVal = isDelayCard(_gameBoardSide[1]._handCard[i]._cardId);
+ if (tmpVal != -1) {
+ victimId = -1;
+ int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
+
+ for (int j = 0; j <= 3; j++) {
+ if (rndVal != 1) {
+ if ((_gameBoardSide[rndVal]._delayCard._cardId == 0) && isAttackPossible(rndVal, _gameBoardSide[1]._handCard[i]._cardId))
+ victimId = rndVal;
+ }
+
+ if (victimId != -1) {
+ playDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[victimId]._delayCard);
+ return;
+ } else {
+ rndVal--;
+ if (rndVal < 0)
+ rndVal = 3;
+ }
+ }
+ }
+ }
+
+ for (int j = 0; j <= 3; j++) {
+ if (getStationCardId(_gameBoardSide[1]._handCard[j]._cardId) != -1) {
+ victimId = -1;
+ int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
+ for (int l = 0; l <= 3; l++) {
+ if (rndVal != 1) {
+ if ((_gameBoardSide[rndVal]._delayCard._cardId == 0) && (_gameBoardSide[1]._handCard[j]._cardId == 1))
+ victimId = rndVal;
+ }
+ if (victimId != -1) {
+ playDelayCard(&_gameBoardSide[1]._handCard[j], &_gameBoardSide[victimId]._delayCard);
+ return;
+ } else {
+ rndVal--;
+ if (rndVal < 0)
+ rndVal = 3;
+ }
+ }
+ }
+ }
+
+ handlePlayer01Discard(1);
+}
+
+void Scene1337::handlePlayer3() {
+ if (_gameBoardSide[3]._delayCard._cardId != 0) {
+ switch (_gameBoardSide[3]._delayCard._cardId) {
+ case 10:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 17:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 21:
+ discardCard(&_gameBoardSide[3]._delayCard);
+ return;
+ default:
+ for (int i = 0; i <= 3; i++) {
+ if (checkAntiDelayCard(_gameBoardSide[3]._delayCard._cardId, _gameBoardSide[3]._handCard[i]._cardId)) {
+ playAntiDelayCard(&_gameBoardSide[3]._handCard[i], &_gameBoardSide[3]._delayCard);
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ int randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
+ if (_gameBoardSide[3]._handCard[randIndx]._cardId == 1) {
+ // Station Card
+ for (int i = 0; i <= 7; i++) {
+ if ((_gameBoardSide[3]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[3]._delayCard._cardId)) {
+ playPlatformCard(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[3]._outpostStation[i]);
+ return;
+ }
+ }
+ } else if (_gameBoardSide[3]._handCard[randIndx]._cardId <= 9) {
+ // Outpost Card
+ for (int i = 0; i <= 7; i++) {
+ if (_gameBoardSide[3]._outpostStation[i]._cardId == _gameBoardSide[3]._handCard[randIndx]._cardId) {
+ discardCard(&_gameBoardSide[3]._handCard[randIndx]);
+ return;
+ }
+ }
+
+ for (int i = 0; i <= 7; i++) {
+ if ((_gameBoardSide[3]._outpostStation[i]._cardId == 1) && !isStopConstructionCard(_gameBoardSide[3]._delayCard._cardId)) {
+ int stationCount = 0;
+ for (int j = 0; j <= 7; j++) {
+ if ((_gameBoardSide[3]._outpostStation[j]._cardId > 1) && (_gameBoardSide[3]._outpostStation[j]._cardId <= 9))
+ ++stationCount;
+ }
+
+ if (stationCount == 7)
+ _winnerId = 3;
+
+ playStationCard(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[3]._outpostStation[i]);
+ return;
+ }
+ }
+ } else if (_gameBoardSide[3]._handCard[randIndx]._cardId == 13) {
+ // Meteor Card
+ int victimId = getPlayerWithOutpost(3);
+
+ if (victimId != -1) {
+ playCentralOutpostCard(&_gameBoardSide[3]._handCard[randIndx], victimId);
+ return;
+ }
+ } else if (_gameBoardSide[3]._handCard[randIndx]._cardId == 25) {
+ // Thief card
+ int victimId = -1;
+ int tmpRandIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
+
+ for (int i = 0; i <= 3; i++) {
+ if ( (tmpRandIndx != 3)
+ && ( (_gameBoardSide[tmpRandIndx]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[tmpRandIndx]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[tmpRandIndx]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[tmpRandIndx]._handCard[3]._cardId != 0) )) {
+ victimId = tmpRandIndx;
+ break;
+ }
+
+ ++tmpRandIndx;
+ if (tmpRandIndx > 3)
+ tmpRandIndx = 0;
+ }
+
+ if (victimId != -1) {
+ playThieftCard(3, &_gameBoardSide[3]._handCard[randIndx], victimId);
+ return;
+ }
+ } else {
+ switch (_gameBoardSide[3]._handCard[randIndx]._cardId) {
+ case 10:
+ // No break on purpose
+ case 11:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 14:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 17:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 21:
+ // No break on purpose
+ case 24: {
+ int victimId = -1;
+ int tmpRandIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
+
+ for (int i = 0; i <= 3; i++) {
+ if (tmpRandIndx != 3) {
+ if ((_gameBoardSide[tmpRandIndx]._delayCard._cardId == 0)
+ && isAttackPossible(tmpRandIndx, _gameBoardSide[3]._handCard[randIndx]._cardId))
+ victimId = tmpRandIndx;
+ }
+
+ ++tmpRandIndx;
+ if (tmpRandIndx > 3)
+ tmpRandIndx = 0;
+
+ if (victimId != -1)
+ break;
+ }
+
+ if (victimId != -1) {
+ // Useless second identical check skipped
+ playDelayCard(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[victimId]._delayCard);
+ return;
+ }
+ }
+ default:
+ break;
+ }
+ }
+
+ discardCard(&_gameBoardSide[3]._handCard[randIndx]);
+}
+
+void Scene1337::handleAutoplayPlayer2() {
+ if (getStationCardId(this->_gameBoardSide[2]._delayCard._cardId) == -1)
+ _delayedFunction = &Scene1337::handlePlayer2;
+ else
+ discardCard(&_gameBoardSide[2]._delayCard);
+}
+
+void Scene1337::handlePlayer2() {
+ _selectedCard._stationPos = g_globals->_events._mousePos;
+
+ if (R2_GLOBALS._v57810 == 200) {
+ // Hand
+ int i;
+ for (i = 0; i < 4; i++) {
+ if ((_gameBoardSide[2]._handCard[i].isIn(_selectedCard._stationPos)) && (_gameBoardSide[2]._handCard[i]._cardId != 0)) {
+ Card *handcard = &_gameBoardSide[2]._handCard[i];
+ _selectedCard._cardId = handcard->_cardId;
+ _selectedCard._stationPos = handcard->_stationPos;
+ //warning("_selectedCard._actorName = handcard->_actorName;");
+ //warning("_selectedCard._fieldE = handcard->_fieldE;");
+ //warning("_selectedCard._field10 = handcard->_field10;");
+ //warning("_selectedCard._field12 = handcard->_field12;");
+ //warning("_selectedCard._field14 = handcard->_field14;");
+ //warning("_selectedCard._field16 = handcard->_field16;");
+ _selectedCard._sceneRegionId = handcard->_sceneRegionId;
+ _selectedCard._position = handcard->_position;
+ _selectedCard._yDiff = handcard->_yDiff;
+ _selectedCard._bounds = handcard->_bounds;
+ _selectedCard._resNum = handcard->_resNum;
+ _selectedCard._lookLineNum = handcard->_lookLineNum;
+ _selectedCard._talkLineNum = handcard->_talkLineNum;
+ _selectedCard._useLineNum = handcard->_useLineNum;
+ _selectedCard._action = handcard->_action;
+ //warning("_selectedCard._field0 = handcard->_field0;");
+ _selectedCard._card._updateStartFrame = handcard->_card._updateStartFrame;
+ _selectedCard._card._walkStartFrame = handcard->_card._walkStartFrame;
+ _selectedCard._card._oldPosition = handcard->_card._oldPosition;
+ _selectedCard._card._percent = handcard->_card._percent;
+ _selectedCard._card._priority = handcard->_card._priority;
+ _selectedCard._card._angle = handcard->_card._angle;
+ _selectedCard._card._flags = handcard->_card._flags;
+ _selectedCard._card._xe = handcard->_card._xe;
+ _selectedCard._card._xs = handcard->_card._xs;
+ _selectedCard._card._paneRects[0] = handcard->_card._paneRects[0];
+ _selectedCard._card._paneRects[1] = handcard->_card._paneRects[1];
+ _selectedCard._card._visage = handcard->_card._visage;
+ _selectedCard._card._objectWrapper = handcard->_card._objectWrapper;
+ _selectedCard._card._strip = handcard->_card._strip;
+ _selectedCard._card._animateMode = handcard->_card._animateMode;
+ _selectedCard._card._frame = handcard->_card._frame;
+ _selectedCard._card._endFrame = handcard->_card._endFrame;
+ _selectedCard._card._loopCount = handcard->_card._loopCount;
+ _selectedCard._card._frameChange = handcard->_card._frameChange;
+ _selectedCard._card._numFrames = handcard->_card._numFrames;
+ _selectedCard._card._regionIndex = handcard->_card._regionIndex;
+ _selectedCard._card._mover = handcard->_card._mover;
+ _selectedCard._card._moveDiff = handcard->_card._moveDiff;
+ _selectedCard._card._moveRate = handcard->_card._moveRate;
+ _selectedCard._card._actorDestPos = handcard->_card._actorDestPos;
+ _selectedCard._card._endAction = handcard->_card._endAction;
+ _selectedCard._card._regionBitList = handcard->_card._regionBitList;
+ // _selectedCard._object1._actorName = handcard->_object1._actorName;
+ //warning("_selectedCard._card._fieldE = handcard->_card._fieldE;");
+ //warning("_selectedCard._card._field10 = handcard->_card._field10;");
+ //warning("_selectedCard._card._field12 = handcard->_card._field12;");
+ //warning("_selectedCard._card._field14 = handcard->_card._field14;");
+ //warning("_selectedCard._card._field16 = handcard->_card._field16;");
+
+ _gameBoardSide[2]._handCard[i]._cardId = 0;
+ _gameBoardSide[2]._handCard[i]._card.remove();
+ break;
+ }
+ }
+
+ if (i == 4) {
+ handleClick(1, _selectedCard._stationPos);
+ handleAutoplayPlayer2();
+ return;
+ } else {
+ setCursorData(1332, _selectedCard._card._strip, _selectedCard._card._frame);
+ R2_GLOBALS._sceneObjects->draw();
+ }
+ } else if (R2_GLOBALS._v57810 == 300) {
+ // Eye
+ handleClick(3, _selectedCard._stationPos);
+ handleAutoplayPlayer2();
+ return;
+ } else {
+ // The original code is calling a function full of dead code.
+ // Only this message remains after a cleanup.
+ MessageDialog::show(WRONG_ANSWER_MSG, OK_BTN_STRING);
+ //
+ handleAutoplayPlayer2();
+ return;
+ }
+
+ Event event;
+ bool found;
+ for (;;) {
+ if ( ((g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN)) && (event.btnState == BTNSHIFT_RIGHT))
+ || (g_globals->_events.getEvent(event, EVENT_KEYPRESS)) ){
+ _selectedCard._stationPos = g_globals->_events._mousePos;
+ found = false;
+
+ for (int i = 0; i <= 3; i ++) {
+ if (_gameBoardSide[2]._handCard[i].isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if (_gameBoardSide[2]._handCard[i]._cardId == 0) {
+ _gameBoardSide[2]._handCard[i]._cardId = _selectedCard._cardId;
+ _gameBoardSide[2]._handCard[i]._card.postInit();
+ _gameBoardSide[2]._handCard[i]._card.hide();
+ _gameBoardSide[2]._handCard[i]._card.setVisage(1332);
+ _gameBoardSide[2]._handCard[i]._card.setPosition(_gameBoardSide[2]._handCard[i]._stationPos, 0);
+ _gameBoardSide[2]._handCard[i]._card.fixPriority(170);
+ setAnimationInfo(&_gameBoardSide[2]._handCard[i]);
+ setCursorData(5, 1, 4);
+ _currentPlayerNumb--;
+ _showPlayerTurn = false;
+ handleNextTurn();
+ return;
+ } else {
+ actionDisplay(1330, 127, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ found = true;
+ }
+ break;
+ }
+ }
+
+ if (!found) {
+ if (_discardPile.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ discardCard(&_selectedCard);
+ return;
+ } else if (_selectedCard._cardId == 1) {
+ bool isInCardFl = false;
+ int i;
+ for (i = 0; i <= 7; i++) {
+ if (_gameBoardSide[2]._outpostStation[i].isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ isInCardFl = true;
+ break;
+ }
+ }
+
+ if ((isInCardFl) && (_gameBoardSide[2]._outpostStation[i]._cardId == 0)) {
+ if (isDelayCard(_gameBoardSide[2]._delayCard._cardId) != -1) {
+ actionDisplay(1330, 55, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else {
+ playPlatformCard(&_selectedCard, &_gameBoardSide[2]._outpostStation[i]);
+ return;
+ }
+ } else {
+ actionDisplay(1330, 56, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else if (_selectedCard._cardId <= 9) {
+ bool isInCardFl = false;
+ int i;
+ for (i = 0; i <= 7; i++) {
+ if (_gameBoardSide[2]._outpostStation[i].isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ isInCardFl = true;
+ break;
+ }
+ }
+ if ((isInCardFl) && (_gameBoardSide[2]._outpostStation[i]._cardId == 1)) {
+ isInCardFl = false;
+ for (int j = 0; j <= 7; j++) {
+ if (_selectedCard._cardId == _gameBoardSide[2]._outpostStation[j]._cardId) {
+ isInCardFl = true;
+ break;
+ }
+ }
+ if (isInCardFl) {
+ // This station is already in place
+ actionDisplay(1330, 34, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (isDelayCard(_gameBoardSide[2]._delayCard._cardId) != -1) {
+ // You must eliminate your delay before you can play a station
+ actionDisplay(1330, 35, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else {
+ int stationCount = 0;
+ for (int k = 0; k <= 7; k++) {
+ if ((_gameBoardSide[2]._outpostStation[k]._cardId > 1) && (_gameBoardSide[2]._outpostStation[k]._cardId <= 9))
+ ++stationCount;
+ }
+
+ if (stationCount == 7)
+ _winnerId = 2;
+
+ playStationCard(&_selectedCard, &_gameBoardSide[2]._outpostStation[i]);
+ return;
+ }
+ } else {
+ actionDisplay(1330, 37, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else if ((_selectedCard._cardId == 26) || (_selectedCard._cardId == 30) ||(_selectedCard._cardId == 32) || (_selectedCard._cardId == 28)) {
+ // Check anti-delay card (26 = Diplomacy, 28 = Innovation, 30 = Cure, 32 = Agreement)
+ if (_gameBoardSide[2]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ actionDisplay(1330, 42, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (checkAntiDelayCard(_gameBoardSide[2]._delayCard._cardId, _selectedCard._cardId)) {
+ playAntiDelayCard(&_selectedCard, &_gameBoardSide[2]._delayCard);
+ return;
+ } else {
+ if (_gameBoardSide[2]._delayCard._cardId != 0) {
+ switch (_gameBoardSide[2]._delayCard._cardId) {
+ case 11:
+ actionDisplay(1330, 68, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 14:
+ actionDisplay(1330, 80, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 16:
+ actionDisplay(1330, 84, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 24:
+ actionDisplay(1330, 96, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ } else {
+ actionDisplay(1330, 41, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ }
+ } else if ((getStationCardId(_selectedCard._cardId) == -1) && (isDelayCard(_selectedCard._cardId) == -1)) {
+ if (_selectedCard._cardId == 13) {
+ // Meteor Card
+ if (_gameBoardSide[0]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ for (int k = 0; k <= 7; k++) {
+ if (_gameBoardSide[0]._outpostStation[k]._cardId != 0) {
+ playCentralOutpostCard(&_selectedCard, 0);
+ return;
+ }
+ }
+ actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (_gameBoardSide[3]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ for (int k = 0; k <= 7; k++) {
+ if (_gameBoardSide[3]._outpostStation[k]._cardId != 0) {
+ playCentralOutpostCard(&_selectedCard, 3);
+ return;
+ }
+ }
+ actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (_gameBoardSide[1]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ for (int k = 0; k <= 7; k++) {
+ if (_gameBoardSide[1]._outpostStation[k]._cardId == 0) {
+ playCentralOutpostCard(&_selectedCard, 1);
+ return;
+ }
+ }
+ actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else {
+ actionDisplay(1330, 128, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else if (_selectedCard._cardId == 25) {
+ // Thief card
+ if (_gameBoardSide[0]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if ( (_gameBoardSide[0]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[0]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[0]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[0]._handCard[3]._cardId != 0) ) {
+ int k;
+ for (k = 0; k <= 3; k++){
+ if (_gameBoardSide[2]._handCard[k]._cardId == 0)
+ break;
+ }
+ playThieftCard(2, &_gameBoardSide[2]._handCard[k], 0);
+ return;
+ } else {
+ actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else if (_gameBoardSide[1]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if ( (_gameBoardSide[1]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[1]._handCard[3]._cardId != 0) ) {
+ int k;
+ for (k = 0; k <= 3; k++){
+ if (_gameBoardSide[2]._handCard[k]._cardId == 0)
+ break;
+ }
+ playThieftCard(2, &_gameBoardSide[2]._handCard[k], 1);
+ return;
+ } else {
+ actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ }
+
+ if (_gameBoardSide[3]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if ( (_gameBoardSide[3]._handCard[0]._cardId != 0)
+ || (_gameBoardSide[3]._handCard[1]._cardId != 0)
+ || (_gameBoardSide[3]._handCard[2]._cardId != 0)
+ || (_gameBoardSide[3]._handCard[3]._cardId != 0) ) {
+ int k;
+ for (k = 0; k <= 3; k++){
+ if (_gameBoardSide[2]._handCard[k]._cardId == 0)
+ break;
+ }
+ playThieftCard(2, &_gameBoardSide[2]._handCard[k], 3);
+ return;
+ } else {
+ actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else {
+ actionDisplay(1330, 129, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else if (_selectedCard._cardId == 29) {
+ // Interceptor cards are used to prevent collision
+ actionDisplay(1330, 136, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (_selectedCard._cardId == 27) {
+ actionDisplay(1330, 137, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ } else if (_gameBoardSide[0]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if (_gameBoardSide[0]._delayCard._cardId != 0) {
+ actionDisplay(1330, 15, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (!isAttackPossible(0, _selectedCard._cardId)) {
+ switch (_selectedCard._cardId) {
+ case 10:
+ actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 12:
+ actionDisplay(1330, 70, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ actionDisplay(1330, 82, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 17:
+ actionDisplay(1330, 86, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 18:
+ actionDisplay(1330, 88, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 19:
+ actionDisplay(1330, 90, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ actionDisplay(1330, 92, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 21:
+ actionDisplay(1330, 94, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ } else {
+ playDelayCard(&_selectedCard, &_gameBoardSide[0]._delayCard);
+ return;
+ }
+ } else if (_gameBoardSide[3]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if (_gameBoardSide[3]._delayCard._cardId != 0) {
+ actionDisplay(1330, 17, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (!isAttackPossible(3, _selectedCard._cardId)) {
+ switch (_selectedCard._cardId) {
+ case 10:
+ actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 12:
+ actionDisplay(1330, 70, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ actionDisplay(1330, 82, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 17:
+ actionDisplay(1330, 86, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 18:
+ actionDisplay(1330, 88, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 19:
+ actionDisplay(1330, 90, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ actionDisplay(1330, 92, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 21:
+ actionDisplay(1330, 94, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ } else {
+ playDelayCard(&_selectedCard, &_gameBoardSide[3]._delayCard);
+ return;
+ }
+ } else if (_gameBoardSide[1]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
+ if (_gameBoardSide[1]._delayCard._cardId != 0) {
+ actionDisplay(1330, 19, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ } else if (!isAttackPossible(1, _selectedCard._cardId)) {
+ switch (_selectedCard._cardId) {
+ case 10:
+ actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 12:
+ actionDisplay(1330, 70, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 15:
+ actionDisplay(1330, 82, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 17:
+ actionDisplay(1330, 86, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 18:
+ actionDisplay(1330, 88, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 19:
+ actionDisplay(1330, 90, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 20:
+ actionDisplay(1330, 92, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ case 21:
+ actionDisplay(1330, 94, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ break;
+ default:
+ break;
+ }
+ } else {
+ playDelayCard(&_selectedCard, &_gameBoardSide[1]._delayCard);
+ return;
+ }
+ } else {
+ actionDisplay(1330, 38, 159, 10, 1, 200, 0, 7, 0, 154, 154);
+ }
+ }
+ } else {
+ g_globals->_scenePalette.signalListeners();
+ R2_GLOBALS._sceneObjects->draw();
+ g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
+ }
+
+ g_globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
+ }
+}
+
+void Scene1337::updateCursorId(int cursorId, bool updateFl) {
+ if ((R2_GLOBALS._v57709 != 0) || (R2_GLOBALS._v5780C != 0))
+ return;
+
+ R2_GLOBALS._mouseCursorId = cursorId;
+
+ if (updateFl) {
+ R2_GLOBALS._mouseCursorId++;
+
+ if (R2_GLOBALS._mouseCursorId < 1)
+ R2_GLOBALS._mouseCursorId = 2;
+
+ if (R2_GLOBALS._mouseCursorId > 2)
+ R2_GLOBALS._mouseCursorId = 1;
+ }
+
+ // The original was using an intermediate function to call setCursorData.
+ // It has been removed to improve readability
+ if (R2_GLOBALS._mouseCursorId == 1) {
+ R2_GLOBALS._v57810 = 200;
+ setCursorData(5, 1, 4);
+ } else if (R2_GLOBALS._mouseCursorId == 2) {
+ R2_GLOBALS._v57810 = 300;
+ setCursorData(5, 1, 5);
+ } else {
+ R2_GLOBALS._v57810 = 0;
+ setCursorData(5, 0, 0);
+ }
+}
+
+void Scene1337::setCursorData(int resNum, int rlbNum, int frameNum) {
+ _cursorCurRes = resNum;
+ _cursorCurStrip = rlbNum;
+ _cursorCurFrame = frameNum;
+
+ if (!frameNum) {
+ // Should be a hardcoded cursor displaying only a dot.
+ // FIXME: Use another cursor when possible
+ R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
+ } else {
+ // TODO: The original was using some resource caching, which was useless and complex
+ // and which has been removed. This cursor behavior clearly made intensive use of this caching...
+ // We now have to find a way to cache these cursor pointers and avoid loading them multiple times per seconds
+ uint size;
+ byte *cursor = g_resourceManager->getSubResource(resNum, rlbNum, frameNum, &size);
+ // Decode the cursor
+ GfxSurface s = surfaceFromRes(cursor);
+
+ Graphics::Surface surface = s.lockSurface();
+ const byte *cursorData = (const byte *)surface.getPixels();
+ CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
+ s.unlockSurface();
+
+ DEALLOCATE(cursor);
+ }
+}
+
+void Scene1337::subD18F5() {
+ if (R2_GLOBALS._v57709 == 0)
+ // The original restores a copy of the default cursor (the hand), which isn't possible with our implementation
+ // We reload that cursor instead.
+ setCursorData(5, 1, 4);
+
+ ++R2_GLOBALS._v57709;
+}
+
+void Scene1337::subD1917() {
+ if (R2_GLOBALS._v57709 != 0) {
+ R2_GLOBALS._v57709--;
+ if (R2_GLOBALS._v57709 == 0) {
+ // The original was using an intermediate function to call setCursorData.
+ // It has been removed to improve readability
+ setCursorData(5, _cursorCurStrip, _cursorCurFrame);
+ }
+ }
+}
+
+void Scene1337::subD1940(bool flag) {
+ if (flag)
+ ++R2_GLOBALS._v5780C;
+ else if (R2_GLOBALS._v5780C != 0)
+ --R2_GLOBALS._v5780C;
+}
+
+void Scene1337::subD1975(int arg1, int arg2) {
+ // No implementation required in ScummVM: Mouse handling with tons of caching
+}
+
+void Scene1337::OptionsDialog::show() {
+ OptionsDialog *dlg = new OptionsDialog();
+ dlg->draw();
+
+ // Show the dialog
+ GfxButton *btn = dlg->execute(NULL);
+
+ // Figure out the new selected character
+ if (btn == &dlg->_quitGame)
+ R2_GLOBALS._sceneManager.changeScene(125);
+ else if (btn == &dlg->_restartGame)
+ R2_GLOBALS._sceneManager.changeScene(1330);
+
+ // Remove the dialog
+ dlg->remove();
+ delete dlg;
+}
+
+Scene1337::OptionsDialog::OptionsDialog() {
+ // Set the elements text
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+ _autoplay.setText(scene->_autoplay ? AUTO_PLAY_ON : AUTO_PLAY_OFF);
+ _restartGame.setText(START_NEW_CARD_GAME);
+ _quitGame.setText(QUIT_CARD_GAME);
+ _continueGame.setText(CONTINUE_CARD_GAME);
+
+ // Set position of the elements
+ _autoplay._bounds.moveTo(5, 2);
+ _restartGame._bounds.moveTo(5, _autoplay._bounds.bottom + 2);
+ _quitGame._bounds.moveTo(5, _restartGame._bounds.bottom + 2);
+ _continueGame._bounds.moveTo(5, _quitGame._bounds.bottom + 2);
+
+ // Add the items to the dialog
+ addElements(&_autoplay, &_restartGame, &_quitGame, &_continueGame, NULL);
+
+ // Set the dialog size and position
+ frame();
+ _bounds.collapse(-6, -6);
+ setCenter(160, 100);
+}
+
+GfxButton *Scene1337::OptionsDialog::execute(GfxButton *defaultButton) {
+ _gfxManager.activate();
+
+ // Event loop
+ GfxButton *selectedButton = NULL;
+
+ bool breakFlag = false;
+ while (!g_vm->shouldQuit() && !breakFlag) {
+ Event event;
+ while (g_globals->_events.getEvent(event) && !breakFlag) {
+ // Adjust mouse positions to be relative within the dialog
+ event.mousePos.x -= _gfxManager._bounds.left;
+ event.mousePos.y -= _gfxManager._bounds.top;
+
+ for (GfxElementList::iterator i = _elements.begin(); i != _elements.end(); ++i) {
+ if ((*i)->process(event))
+ selectedButton = static_cast<GfxButton *>(*i);
+ }
+
+ if (selectedButton == &_autoplay) {
+ // Toggle Autoplay
+ selectedButton = NULL;
+ Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
+ scene->_autoplay = !scene->_autoplay;
+
+ _autoplay.setText(scene->_autoplay ? AUTO_PLAY_ON : AUTO_PLAY_OFF);
+ _autoplay.draw();
+ } else if (selectedButton) {
+ breakFlag = true;
+ break;
+ } else if (!event.handled) {
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ selectedButton = NULL;
+ breakFlag = true;
+ break;
+ }
+ }
+ }
+
+ g_system->delayMillis(10);
+ GLOBALS._screenSurface.updateScreen();
+ }
+
+ _gfxManager.deactivate();
+ return selectedButton;
+}
+
+} // End of namespace Ringworld2
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_outpost.h b/engines/tsage/ringworld2/ringworld2_outpost.h
new file mode 100644
index 0000000000..6c6952c196
--- /dev/null
+++ b/engines/tsage/ringworld2/ringworld2_outpost.h
@@ -0,0 +1,259 @@
+/* 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.
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD2_OUTPOST_H
+#define TSAGE_RINGWORLD2_OUTPOST_H
+
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/sound.h"
+#include "tsage/ringworld2/ringworld2_logic.h"
+
+namespace TsAGE {
+
+namespace Ringworld2 {
+
+using namespace TsAGE;
+
+class Scene1337 : public SceneExt {
+ class OptionsDialog: public GfxDialog {
+ private:
+ GfxButton _autoplay;
+ GfxButton _restartGame;
+ GfxButton _quitGame;
+ GfxButton _continueGame;
+
+ OptionsDialog();
+ virtual ~OptionsDialog() {}
+ virtual GfxButton *execute(GfxButton *defaultButton);
+ public:
+ static void show();
+ };
+
+ class Card: public SceneHotspot {
+ public:
+ SceneObject _card;
+
+ int _cardId;
+ Common::Point _stationPos;
+
+ Card();
+ void synchronize(Serializer &s);
+ bool isIn(Common::Point pt);
+ };
+
+ class GameBoardSide: public SceneHotspot {
+ public:
+ Card _handCard[4];
+ Card _outpostStation[8];
+ Card _delayCard;
+ Card _emptyStationPos;
+
+ Common::Point _card1Pos;
+ Common::Point _card2Pos;
+ Common::Point _card3Pos;
+ Common::Point _card4Pos;
+ int _frameNum;
+
+ GameBoardSide();
+ void synchronize(Serializer &s);
+ };
+
+ class Action1337: public Action {
+ public:
+ void waitFrames(int32 frameCount);
+ };
+
+ class Action1: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action2: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action3: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action4: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action5: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action6: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action7: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action8: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action9: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action10: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action11: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action12: public Action1337 {
+ public:
+ void signal();
+ };
+ class Action13: public Action1337 {
+ public:
+ void signal();
+ };
+public:
+ Action1 _action1;
+ Action2 _action2;
+ Action3 _action3;
+ Action4 _action4;
+ Action5 _action5;
+ Action6 _action6;
+ Action7 _action7;
+ Action8 _action8;
+ Action9 _action9;
+ Action10 _action10;
+ Action11 _action11;
+ Action12 _action12;
+ Action13 _action13;
+
+ typedef void (Scene1337::*FunctionPtrType)();
+ FunctionPtrType _delayedFunction;
+
+ bool _autoplay;
+ bool _shuffleEndedFl;
+ bool _showPlayerTurn;
+ bool _displayHelpFl;
+ bool _instructionsDisplayedFl;
+
+ // Discarded cards are put in the available cards pile, with an higher index so there no conflict
+ int _currentDiscardIndex;
+ int _availableCardsPile[100];
+ int _cardsAvailableNumb;
+ int _currentPlayerNumb;
+ int _actionPlayerIdx;
+ int _actionVictimIdx;
+ int _winnerId;
+ int _instructionsWaitCount;
+ int _cursorCurRes;
+ int _cursorCurStrip;
+ int _cursorCurFrame;
+
+ ASound _aSound1;
+ ASound _aSound2;
+ GameBoardSide _gameBoardSide[4];
+ SceneActor _helpIcon;
+ SceneActor _stockPile;
+ SceneItem _actionItem;
+ SceneObject _currentPlayerArrow;
+
+ Card *_actionCard1;
+ Card *_actionCard2;
+ Card *_actionCard3;
+ Card _animatedCard;
+ Card _shuffleAnimation;
+ Card _discardedPlatformCard;
+ Card _selectedCard;
+ Card _discardPile;
+ Card _stockCard;
+
+ SceneObject _upperDisplayCard[8];
+ SceneObject _lowerDisplayCard[8];
+
+ Scene1337();
+ virtual void synchronize(Serializer &s);
+
+ void actionDisplay(int resNum, int lineNum, int x, int y, int keepOnScreen, int width, int textMode, int fontNum, int colFG, int colBGExt, int colFGExt);
+ void setAnimationInfo(Card *card);
+ void handleNextTurn();
+ void handlePlayerTurn();
+ bool isStationCard(int cardId);
+ bool isStopConstructionCard(int cardId);
+ int getStationId(int playerId, int handCardId);
+ int findPlatformCardInHand(int playerId);
+ int findMeteorCardInHand(int playerId);
+ int findThieftCardInHand(int playerId);
+ int isDelayCard(int cardId);
+ int getStationCardId(int cardId);
+ void handlePlayer01Discard(int playerId);
+ void playThieftCard(int playerId, Card *card, int victimId);
+ int getPreventionCardId(int cardId);
+ bool isAttackPossible(int victimId, int cardId);
+ int getPlayerWithOutpost(int playerId);
+ bool checkAntiDelayCard(int delayCardId, int cardId);
+ void playStationCard(Card *station, Card *platform);
+ void playDelayCard(Card *card, Card *dest);
+ void playPlatformCard(Card *card, Card *dest);
+ void playAntiDelayCard(Card *card, Card *dest);
+ Card *getStationCard(int arg1);
+ void playCentralOutpostCard(Card *card, int playerId);
+ int getRandomCardFromHand(int playerId);
+ void discardCard(Card *card);
+ void subC4CD2();
+ void subC4CEC();
+ void playInterceptorCard(Card *subObj1, Card *subObj2);
+ void displayDialog(int dialogNumb);
+ void subPostInit();
+ void displayInstructions();
+ void suggestInstructions();
+ void shuffleCards();
+ void dealCards();
+ void showOptionsDialog();
+ void handleClick(int arg1, Common::Point pt);
+ void handlePlayer0();
+ void handlePlayer1();
+ void handlePlayer2();
+ void handlePlayer3();
+ void handleAutoplayPlayer2();
+ void updateCursorId(int arg1, bool arg2);
+ void setCursorData(int resNum, int rlbNum, int frameNum);
+ void subD18F5();
+ void subD1917();
+ void subD1940(bool flag);
+ void subD1975(int arg1, int arg2);
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void process(Event &event);
+ virtual void dispatch();
+};
+
+} // End of namespace Ringworld2
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index b82565332a..573cbbb29a 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -627,7 +627,7 @@ void Scene125::postInit(SceneObjectList *OwnerList) {
SceneExt::postInit();
_palette.loadPalette(0);
- if (R2_GLOBALS._sceneManager._previousScene != 125)
+ if ((R2_GLOBALS._sceneManager._previousScene != 125) && (R2_GLOBALS._sceneManager._previousScene != 1337) && (R2_GLOBALS._sceneManager._previousScene != 1330))
// Save the prior scene to return to when the console is turned off
R2_GLOBALS._player._oldCharacterScene[R2_QUINN] = R2_GLOBALS._sceneManager._previousScene;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
index e2c22bd0b4..81dc05e2a4 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
@@ -1321,5469 +1321,6 @@ void Scene1100::saveCharacter(int characterIndex) {
}
/*--------------------------------------------------------------------------
- * Scene 1200 - Air Ducts Maze
- *
- *--------------------------------------------------------------------------*/
-
-Scene1200::Scene1200() {
- _nextCrawlDirection = 0;
- _field414 = 0;
- _field416 = 0;
- _field418 = 0;
- _field41A = 0;
- _fixupMaze = false;
-}
-
-void Scene1200::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
-
- s.syncAsSint16LE(_nextCrawlDirection);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
- s.syncAsSint16LE(_field418);
- s.syncAsSint16LE(_field41A);
- s.syncAsSint16LE(_fixupMaze);
-}
-
-Scene1200::LaserPanel::LaserPanel() {
-}
-
-void Scene1200::LaserPanel::Jumper::init(int state) {
- _state = state;
-
- SceneActor::postInit();
- setup(1003, 1, 1);
- fixPriority(255);
-
- switch (_state) {
- case 1:
- switch (R2_GLOBALS._ductMazePanel1State) {
- case 1:
- setFrame2(2);
- setPosition(Common::Point(129, 101));
- break;
- case 2:
- setFrame2(3);
- setPosition(Common::Point(135, 95));
- break;
- default:
- break;
- }
- break;
- case 2:
- switch (R2_GLOBALS._ductMazePanel2State) {
- case 1:
- setFrame2(2);
- setPosition(Common::Point(152, 101));
- break;
- case 2:
- setFrame2(3);
- setPosition(Common::Point(158, 122));
- break;
- case 3:
- setFrame2(3);
- setPosition(Common::Point(135, 122));
- break;
- default:
- break;
- }
- break;
- case 3:
- switch (R2_GLOBALS._ductMazePanel3State) {
- case 1:
- setFrame2(3);
- setPosition(Common::Point(158, 95));
- break;
- case 2:
- setFrame2(2);
- setPosition(Common::Point(175, 101));
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- setDetails(1200, 12, -1, -1, 2, (SceneItem *) NULL);
-}
-
-bool Scene1200::LaserPanel::Jumper::startAction(CursorType action, Event &event) {
- if (action != CURSOR_USE)
- return SceneActor::startAction(action, event);
-
- R2_GLOBALS._sound2.play(260);
- switch (_state) {
- case 1:
- if (R2_GLOBALS._ductMazePanel1State == 1) {
- R2_GLOBALS._ductMazePanel1State = 2;
- setFrame2(3);
- setPosition(Common::Point(135, 95));
- } else {
- R2_GLOBALS._ductMazePanel1State = 1;
- setFrame2(2);
- setPosition(Common::Point(129, 101));
- }
- break;
- case 2:
- ++R2_GLOBALS._ductMazePanel2State;
- if (R2_GLOBALS._ductMazePanel2State == 4)
- R2_GLOBALS._ductMazePanel2State = 1;
-
- switch (R2_GLOBALS._ductMazePanel2State) {
- case 1:
- setFrame2(2);
- setPosition(Common::Point(152, 101));
- break;
- case 2:
- setFrame2(3);
- setPosition(Common::Point(158, 122));
- break;
- case 3:
- setFrame2(3);
- setPosition(Common::Point(135, 122));
- break;
- default:
- break;
- }
- break;
- case 3:
- if (R2_GLOBALS._ductMazePanel3State == 1) {
- R2_GLOBALS._ductMazePanel3State = 2;
- setFrame2(2);
- setPosition(Common::Point(175, 101));
- } else {
- R2_GLOBALS._ductMazePanel3State = 1;
- setFrame2(3);
- setPosition(Common::Point(158, 95));
- }
- break;
- default:
- break;
- }
-
- Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
- scene->_field418 = 0;
-
- if ((R2_GLOBALS._ductMazePanel1State == 1) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
- scene->_field418 = 1;
- else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
- scene->_field418 = 2;
- else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 2))
- scene->_field418 = 3;
- else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 3) && (R2_GLOBALS._ductMazePanel3State == 1))
- scene->_field418 = 4;
-
- return true;
-}
-
-void Scene1200::LaserPanel::postInit(SceneObjectList *OwnerList) {
- Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
-
- scene->_field41A = 1;
- R2_GLOBALS._events.setCursor(CURSOR_USE);
- setup2(1003, 1, 1, 100, 40);
- setup3(1200, 11, -1, -1);
- R2_GLOBALS._sound2.play(259);
- _jumper1.init(1);
- _jumper2.init(2);
- _jumper3.init(3);
-
- R2_GLOBALS._player._canWalk = false;
-}
-
-void Scene1200::LaserPanel::remove() {
- Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
-
- scene->_field41A = 0;
- scene->_sceneAreas.remove(&_jumper1);
- scene->_sceneAreas.remove(&_jumper2);
- scene->_sceneAreas.remove(&_jumper3);
- _jumper1.remove();
- _jumper2.remove();
- _jumper3.remove();
-
- ModalWindow::remove();
- R2_GLOBALS._player._canWalk = true;
-}
-
-void Scene1200::postInit(SceneObjectList *OwnerList) {
- loadScene(1200);
- SceneExt::postInit();
-
- if (R2_GLOBALS._sceneManager._previousScene < 3200)
- R2_GLOBALS._sound1.play(257);
-
- _nextCrawlDirection = CRAWL_EAST;
- _field414 = 0;
- _field416 = 0;
- _field418 = 0;
- _field41A = 0;
-
- if ((R2_GLOBALS._ductMazePanel1State == 1) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
- _field418 = 1;
- else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 1))
- _field418 = 2;
- else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 1) && (R2_GLOBALS._ductMazePanel3State == 2))
- _field418 = 3;
- else if ((R2_GLOBALS._ductMazePanel1State == 2) && (R2_GLOBALS._ductMazePanel2State == 3) && (R2_GLOBALS._ductMazePanel3State == 1))
- _field418 = 4;
-
- R2_GLOBALS._player.postInit();
- R2_GLOBALS._player.disableControl();
- R2_GLOBALS._player.setup(3156, 1, 6);
- R2_GLOBALS._player.setPosition(Common::Point(160, 70));
- R2_GLOBALS._player._numFrames = 10;
- R2_GLOBALS._player._oldCharacterScene[R2_MIRANDA] = 1200;
-
- _actor1.postInit();
- _actor1.hide();
-
- _mazeUI.setDisplayBounds(Rect(110, 20, 210, 120));
-
- _mazeUI.postInit();
- _mazeUI.load(1);
- _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
-
- R2_GLOBALS._player.enableControl();
- _item1.setDetails(Rect(0, 0, 320, 200), 1200, 0, 1, 2, 1, NULL);
-}
-
-void Scene1200::signal() {
- switch (_sceneMode++) {
- case 1:
- // No break on purpose
- case 1200:
- // No break on purpose
- case 1201:
- // No break on purpose
- case 1202:
- // No break on purpose
- case 1203:
- R2_GLOBALS._player.enableControl();
- // CHECKME: The original is calling _eventManager.waitEvent();
- _sceneMode = 2;
- break;
- case 10:
- _field416 = 1;
- _field414 = 6;
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.setStrip(1);
- R2_GLOBALS._player.setFrame(5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 11:
- // No break on purpose
- case 21:
- // No break on purpose
- case 31:
- // No break on purpose
- case 41:
- _field416 = 0;
- break;
- case 12:
- _field414 = 14;
- R2_GLOBALS._player._numFrames = 10;
- R2_GLOBALS._player.setup(3155, 1, 4);
- R2_GLOBALS._player.setPosition(Common::Point(160, 70));
- R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
- break;
- case 13:
- // No break on purpose
- case 16:
- // No break on purpose
- case 23:
- // No break on purpose
- case 26:
- // No break on purpose
- case 33:
- // No break on purpose
- case 36:
- // No break on purpose
- case 43:
- // No break on purpose
- case 46:
- R2_GLOBALS._player.setFrame(4);
- _sceneMode = 1;
- setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
- break;
- case 15:
- // No break on purpose
- case 25:
- // No break on purpose
- case 35:
- // No break on purpose
- case 45:
- _field414 = 20;
- R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
- break;
- case 20:
- _field416 = 1;
- _field414 = 6;
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.setStrip(2);
- R2_GLOBALS._player.setFrame(5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 22:
- _field414 = 14;
- R2_GLOBALS._player._numFrames = 10;
- R2_GLOBALS._player.setup(3155, 2, 4);
- R2_GLOBALS._player.setPosition(Common::Point(160, 70));
- R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
- break;
- case 30:
- _field416 = 1;
- _field414 = 6;
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.setStrip(3);
- R2_GLOBALS._player.setFrame(5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 32:
- _field414 = 14;
- R2_GLOBALS._player._numFrames = 10;
- R2_GLOBALS._player.setup(3155, 3, 4);
- R2_GLOBALS._player.setPosition(Common::Point(160, 70));
- R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
- break;
- case 40:
- _field416 = 1;
- _field414 = 6;
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.setStrip(4);
- R2_GLOBALS._player.setFrame(5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 42:
- _field414 = 14;
- R2_GLOBALS._player._numFrames = 10;
- R2_GLOBALS._player.setup(3155, 4, 4);
- R2_GLOBALS._player.setPosition(Common::Point(160, 70));
- R2_GLOBALS._player.animate(ANIM_MODE_2, NULL);
- break;
- case 50:
- // No break on purpose
- case 55:
- // No break on purpose
- case 60:
- R2_GLOBALS._player.setup(3156, 5, 1);
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 51:
- // No break on purpose
- case 56:
- // No break on purpose
- case 117:
- R2_GLOBALS._player.setup(3157, 1, 1);
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 52:
- // No break on purpose
- case 82:
- // No break on purpose
- case 118:
- R2_GLOBALS._player.setup(3156, 3, 6);
- _sceneMode = 1;
- setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
- break;
- case 57:
- // No break on purpose
- case 91:
- // No break on purpose
- case 96:
- R2_GLOBALS._player.setup(3157, 2, 1);
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 58:
- // No break on purpose
- case 92:
- // No break on purpose
- case 122:
- R2_GLOBALS._player.setup(3156, 2, 6);
- _sceneMode = 1;
- setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
- break;
- case 61:
- R2_GLOBALS._player.setup(3157, 4, 5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 62:
- // No break on purpose
- case 72:
- // No break on purpose
- case 98:
- R2_GLOBALS._player.setup(3156, 4, 6);
- _sceneMode = 1;
- setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
- break;
- case 70:
- // No break on purpose
- case 75:
- // No break on purpose
- case 80:
- R2_GLOBALS._player.setup(3156, 6, 1);
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 71:
- // No break on purpose
- case 76:
- // No break on purpose
- case 97:
- R2_GLOBALS._player.setup(3157, 3, 1);
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 77:
- // No break on purpose
- case 111:
- // No break on purpose
- case 116:
- R2_GLOBALS._player.setup(3157, 4, 1);
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 78:
- // No break on purpose
- case 102:
- // No break on purpose
- case 112:
- R2_GLOBALS._player.setup(3156, 1, 6);
- _sceneMode = 1;
- setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL);
- break;
- case 81:
- R2_GLOBALS._player.setup(3157, 2, 5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 90:
- // No break on purpose
- case 95:
- // No break on purpose
- case 100:
- R2_GLOBALS._player.setup(3156, 7, 1);
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 101:
- R2_GLOBALS._player.setup(3157, 1, 5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- case 110:
- // No break on purpose
- case 115:
- // No break on purpose
- case 120:
- R2_GLOBALS._player.setup(3156, 8, 1);
- R2_GLOBALS._player._numFrames = 5;
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- break;
- case 121:
- R2_GLOBALS._player.setup(3157, 3, 5);
- R2_GLOBALS._player.animate(ANIM_MODE_6, this);
- break;
- default:
- // CHECKME: The original is walling _eventManager.waitEvent();
- _sceneMode = 2;
- break;
- }
-}
-
-void Scene1200::process(Event &event) {
- if (_field414 != 0)
- return;
-
- Scene::process(event);
-
- if (!R2_GLOBALS._player._canWalk)
- return;
-
- if (event.eventType == EVENT_BUTTON_DOWN) {
- Common::Point cellPos = R2_GLOBALS._ventCellPos;
- _mazeUI.pixelToCellXY(cellPos);
-
- int cellId = _mazeUI.getCellFromPixelXY(event.mousePos);
- switch (R2_GLOBALS._events.getCursor()) {
- case CURSOR_WALK:
- event.handled = true;
- if ((event.mousePos.x > 179) && (event.mousePos.x < 210) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
- startCrawling(CRAWL_EAST);
-
- if ((event.mousePos.x > 109) && (event.mousePos.x < 140) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
- startCrawling(CRAWL_WEST);
-
- if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 89) && (event.mousePos.y < 120))
- startCrawling(CRAWL_SOUTH);
-
- if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 19) && (event.mousePos.y < 50))
- startCrawling(CRAWL_NORTH);
- break;
- case CURSOR_USE:
- if (cellId > 36) {
- if ( ((cellPos.x == 3) && (cellPos.y == 33))
- || ((cellPos.x == 7) && (cellPos.y == 33))
- || ((cellPos.x == 33) && (cellPos.y == 41))
- || ((cellPos.x == 5) && (cellPos.y == 5))
- || ((cellPos.x == 13) && (cellPos.y == 21))
- || ((cellPos.x == 17) && (cellPos.y == 21))
- || ((cellPos.x == 17) && (cellPos.y == 5))
- || ((cellPos.x == 17) && (cellPos.y == 9))
- || ((cellPos.x == 29) && (cellPos.y == 17))
- || ((cellPos.x == 33) && (cellPos.y == 17))
- || ((cellPos.x == 35) && (cellPos.y == 17))
- || ((cellPos.x == 41) && (cellPos.y == 21)) ) {
- _laserPanel.postInit();
- event.handled = true;
- }
- }
-
- if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
- if ( ((cellPos.x == 3) && (cellPos.y == 9))
- || ((cellPos.x == 11) && (cellPos.y == 27))
- || ((cellPos.x == 17) && (cellPos.y == 7))
- || ((cellPos.x == 17) && (cellPos.y == 27))
- || ((cellPos.x == 17) && (cellPos.y == 33))
- || (cellPos.x == 33) ) {
- switch (cellPos.x) {
- case 3:
- R2_GLOBALS._sceneManager.changeScene(3150);
- break;
- case 33:
- if (R2_GLOBALS._scientistConvIndex >= 4)
- R2_GLOBALS._sceneManager.changeScene(3250);
- else
- SceneItem::display(1200, 6, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
- break;
- default:
- SceneItem::display(1200, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, LIST_END);
- break;
- }
- event.handled = true;
- }
- }
- break;
- case CURSOR_LOOK:
- if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
- event.handled = true;
- switch (cellPos.x) {
- case 3:
- // It was your cell.
- SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- break;
- case 9:
- R2_GLOBALS._sceneManager.changeScene(3240);
- break;
- case 11:
- if (cellPos.y == 27)
- R2_GLOBALS._sceneManager.changeScene(3210);
- else
- // A vent grill
- SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- break;
- case 17:
- switch (cellPos.y) {
- case 5:
- R2_GLOBALS._sceneManager.changeScene(3230);
- break;
- case 21:
- R2_GLOBALS._sceneManager.changeScene(3220);
- break;
- case 33:
- R2_GLOBALS._sceneManager.changeScene(3200);
- break;
- default:
- // A vent grill
- SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- break;
- }
- break;
- case 33:
- R2_GLOBALS._sceneManager.changeScene(3245);
- break;
- default:
- SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- break;
- }
- }
- if (cellId > 36) {
- // "An anti-pest laser"
- event.handled = true;
- SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- }
- break;
- case CURSOR_TALK:
- event.handled = true;
- break;
- default:
- return;
- }
- } else if (event.eventType == EVENT_KEYPRESS) {
- if (_field414) {
- event.handled = false;
- return;
- }
-
- switch (event.kbd.keycode) {
- case Common::KEYCODE_KP8:
- case Common::KEYCODE_UP:
- startCrawling(CRAWL_NORTH);
- break;
- case Common::KEYCODE_KP4:
- case Common::KEYCODE_LEFT:
- startCrawling(CRAWL_WEST);
- break;
- case Common::KEYCODE_KP6:
- case Common::KEYCODE_RIGHT:
- startCrawling(CRAWL_EAST);
- break;
- case Common::KEYCODE_KP2:
- case Common::KEYCODE_DOWN:
- startCrawling(CRAWL_SOUTH);
- break;
- default:
- event.handled = false;
- return;
- break;
- }
- } else
- return;
-}
-
-void Scene1200::dispatch() {
- Rect tmpRect;
- Scene::dispatch();
-
- if (_fixupMaze) {
- _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
- //_mazeUI.draw();
- _fixupMaze = false;
- }
-
- if (_field414 != 0) {
- tmpRect.set(110, 20, 210, 120);
- _field414--;
-
- switch (_nextCrawlDirection) {
- case CRAWL_EAST:
- R2_GLOBALS._ventCellPos.x += 2;
- break;
- case CRAWL_WEST:
- R2_GLOBALS._ventCellPos.x -= 2;
- break;
- case CRAWL_SOUTH:
- R2_GLOBALS._ventCellPos.y += 2;
- break;
- case CRAWL_NORTH:
- R2_GLOBALS._ventCellPos.y -= 2;
- break;
- default:
- break;
- }
-
- _mazeUI.setMazePosition(R2_GLOBALS._ventCellPos);
- //_mazeUI.draw();
-
- if (_field416 != 0) {
- switch(_nextCrawlDirection) {
- case CRAWL_EAST:
- R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x - 2, R2_GLOBALS._player._position.y));
- break;
- case CRAWL_WEST:
- R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x + 2, R2_GLOBALS._player._position.y));
- break;
- case CRAWL_SOUTH:
- R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y - 2));
- break;
- case CRAWL_NORTH:
- R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 2));
- break;
- default:
- break;
- }
- }
- if (_field414 == 0) {
- if (_field416 == 0)
- R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL);
- signal();
- }
- }
-}
-
-void Scene1200::saveCharacter(int characterIndex) {
- R2_GLOBALS._sound1.fadeOut2(NULL);
- SceneExt::saveCharacter(characterIndex);
-}
-
-void Scene1200::startCrawling(CrawlDirection dir) {
- Common::Point cellPos = R2_GLOBALS._ventCellPos;
- _mazeUI.pixelToCellXY(cellPos);
-
- switch (dir) {
- case CRAWL_EAST:
- if ( ((_mazeUI.getCellFromPixelXY(Common::Point(200, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(200, 88)) > 36))
- && ( ((cellPos.x == 3) && (cellPos.y == 33) && (_field418 != 4))
- || ((cellPos.x == 13) && (cellPos.y == 21) && (_field418 != 2))
- || ((cellPos.x == 29) && (cellPos.y == 17) && (_field418 != 1))
- || ((cellPos.x == 33) && (cellPos.y == 41)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1200;
- setAction(&_sequenceManager, this, 1200, &_actor1, NULL);
- } else if (_mazeUI.getCellFromPixelXY(Common::Point(200, 69)) == 36) {
- switch (_nextCrawlDirection) {
- case CRAWL_EAST:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 15;
- else
- _sceneMode = 10;
- break;
- case CRAWL_WEST:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 76;
- else
- _sceneMode = 75;
- break;
- case CRAWL_SOUTH:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 101;
- else
- _sceneMode = 100;
- break;
- case CRAWL_NORTH:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 111;
- else
- _sceneMode = 110;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _nextCrawlDirection = 1;
- signal();
- }
- break;
- case CRAWL_WEST:
- if ( ((_mazeUI.getCellFromPixelXY(Common::Point(120, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(120, 88)) > 36))
- && ( ((cellPos.x == 7) && (cellPos.y == 33) && (_field418 != 4))
- || ((cellPos.x == 17) && (cellPos.y == 21) && (_field418 != 2))
- || ((cellPos.x == 33) && (cellPos.y == 17) && (_field418 != 1))
- || ((cellPos.x == 5) && (cellPos.y == 5)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1201;
- setAction(&_sequenceManager, this, 1201, &_actor1, NULL);
- } else if (_mazeUI.getCellFromPixelXY(Common::Point(120, 69)) == 36) {
- switch (_nextCrawlDirection) {
- case CRAWL_EAST:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 56;
- else
- _sceneMode = 55;
- break;
- case CRAWL_WEST:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 25;
- else
- _sceneMode = 20;
- break;
- case CRAWL_SOUTH:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 91;
- else
- _sceneMode = 90;
- break;
- case CRAWL_NORTH:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 121;
- else
- _sceneMode = 120;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _nextCrawlDirection = 2;
- signal();
- }
- break;
- case CRAWL_SOUTH:
- if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 110)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 110)) > 36))
- && ( ((cellPos.x == 17) && (cellPos.y == 5) && (_field418 != 3))
- || ((cellPos.x == 41) && (cellPos.y == 21)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1203;
- setAction(&_sequenceManager, this, 1203, &_actor1, NULL);
- } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 110)) == 36) {
- switch (_nextCrawlDirection) {
- case CRAWL_EAST:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 51;
- else
- _sceneMode = 50;
- break;
- case CRAWL_WEST:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 81;
- else
- _sceneMode = 80;
- break;
- case CRAWL_SOUTH:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 35;
- else
- _sceneMode = 30;
- break;
- case CRAWL_NORTH:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 116;
- else
- _sceneMode = 115;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _nextCrawlDirection = 3;
- signal();
- }
- break;
- case CRAWL_NORTH:
- if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 30)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 30)) > 36))
- && ( ((cellPos.x == 17) && (cellPos.y == 9) && (_field418 != 3))
- || ((cellPos.x == 35) && (cellPos.y == 17)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1202;
- setAction(&_sequenceManager, this, 1202, &_actor1, NULL);
- } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 30)) == 36) {
- switch (_nextCrawlDirection) {
- case CRAWL_EAST:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 61;
- else
- _sceneMode = 60;
- break;
- case CRAWL_WEST:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 71;
- else
- _sceneMode = 70;
- break;
- case CRAWL_SOUTH:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 96;
- else
- _sceneMode = 95;
- break;
- case CRAWL_NORTH:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 45;
- else
- _sceneMode = 40;
- break;
- default:
- _sceneMode = 1;
- R2_GLOBALS._player.setup(3156, 4, 6);
- break;
- }
- R2_GLOBALS._player.disableControl();
- _nextCrawlDirection = 4;
- signal();
- }
- break;
- default:
- break;
- }
-}
-
-/*--------------------------------------------------------------------------
- * Scene 1337 - Card game
- *
- *--------------------------------------------------------------------------*/
-
-Scene1337::Card::Card() {
- _cardId = 0;
- _stationPos = Common::Point(0, 0);
-}
-
-void Scene1337::Card::synchronize(Serializer &s) {
- warning("STUBBED: Card::synchronize()");
-}
-
-bool Scene1337::Card::isIn(Common::Point pt) {
- if ((_stationPos.x > pt.x) || (_stationPos.x + 24 < pt.x))
- return false;
-
- if ((_stationPos.y > pt.y) || (_stationPos.y + 24 < pt.y))
- return false;
-
- return true;
-}
-
-Scene1337::GameBoardSide::GameBoardSide() {
- _card1Pos = Common::Point(0, 0);
- _card2Pos = Common::Point(0, 0);
- _card3Pos = Common::Point(0, 0);
- _card4Pos = Common::Point(0, 0);
- _frameNum = 0;
-}
-
-void Scene1337::GameBoardSide::synchronize(Serializer &s) {
- warning("STUBBED: GameBoardSide::synchronize()");
-}
-
-Scene1337::Scene1337() {
- _autoplay = false;
- _cardsAvailableNumb = 0;
- _currentDiscardIndex = 0;
-
- for (int i = 0; i < 100; i++)
- _availableCardsPile[i] = 0;
-
- _shuffleEndedFl = false;
- _currentPlayerNumb = 0;
- _actionIdx1 = 0;
- _actionIdx2 = 0;
- _showPlayerTurn = false;
- _displayHelpFl = false;
- _winnerId = -1;
- _instructionsDisplayedFl = false;
- _instructionsWaitCount = 0;
-
- _delayedFunction = nullptr;
- _actionCard1 = nullptr;
- _actionCard2 = nullptr;
- _actionCard3 = nullptr;
-
- _cursorCurRes = 0;
- _cursorCurStrip = 0;
- _cursorCurFrame = 0;
-}
-
-void Scene1337::synchronize(Serializer &s) {
- warning("STUBBED: Scene1337::synchronize()");
-}
-
-void Scene1337::Action1337::waitFrames(int32 frameCount) {
- uint32 firstFrameNumber = g_globals->_events.getFrameNumber();
- uint32 curFrame = firstFrameNumber;
- uint32 destFrame = firstFrameNumber + frameCount;
-
- while ((curFrame < destFrame) && !g_vm->shouldQuit()) {
- TsAGE::Event event;
- g_globals->_events.getEvent(event);
- curFrame = g_globals->_events.getFrameNumber();
- }
-
- // CHECKME: The original is calling _eventManager.waitEvent();
-}
-
-/**
- * Display instructions
- */
-void Scene1337::Action1::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 1: {
- scene->actionDisplay(1331, 6, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- R2_GLOBALS._sceneObjects->draw();
- scene->actionDisplay(1331, 7, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->actionDisplay(1331, 8, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- scene->_gameBoardSide[1]._outpostStation[0]._cardId = 2;
- scene->_gameBoardSide[1]._outpostStation[0]._card.postInit();
- scene->_gameBoardSide[1]._outpostStation[0]._card.setVisage(1332);
- scene->_gameBoardSide[1]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[1]._outpostStation[0]._stationPos, 0);
- scene->_gameBoardSide[1]._outpostStation[0]._card.setStrip(2);
- scene->_gameBoardSide[1]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[1]._outpostStation[0]._cardId);
- scene->_gameBoardSide[1]._outpostStation[0]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[1]._outpostStation[0]);
-
- scene->_gameBoardSide[1]._outpostStation[1]._cardId = 3;
- scene->_gameBoardSide[1]._outpostStation[1]._card.postInit();
- scene->_gameBoardSide[1]._outpostStation[1]._card.setVisage(1332);
- scene->_gameBoardSide[1]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[1]._outpostStation[1]._stationPos, 0);
- scene->_gameBoardSide[1]._outpostStation[1]._card.setStrip(2);
- scene->_gameBoardSide[1]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[1]._outpostStation[1]._cardId);
- scene->_gameBoardSide[1]._outpostStation[1]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[1]._outpostStation[1]);
-
- scene->_gameBoardSide[2]._outpostStation[0]._cardId = 4;
- scene->_gameBoardSide[2]._outpostStation[0]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[0]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[0]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[0]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[0]._cardId);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[0]);
-
- scene->_gameBoardSide[3]._outpostStation[0]._cardId = 5;
- scene->_gameBoardSide[3]._outpostStation[0]._card.postInit();
- scene->_gameBoardSide[3]._outpostStation[0]._card.setVisage(1332);
- scene->_gameBoardSide[3]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[0]._stationPos, 0);
- scene->_gameBoardSide[3]._outpostStation[0]._card.setStrip(2);
- scene->_gameBoardSide[3]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[0]._cardId);
- scene->_gameBoardSide[3]._outpostStation[0]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[0]);
-
- scene->_gameBoardSide[3]._outpostStation[1]._cardId = 6;
- scene->_gameBoardSide[3]._outpostStation[1]._card.postInit();
- scene->_gameBoardSide[3]._outpostStation[1]._card.setVisage(1332);
- scene->_gameBoardSide[3]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[1]._stationPos, 0);
- scene->_gameBoardSide[3]._outpostStation[1]._card.setStrip(2);
- scene->_gameBoardSide[3]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[1]._cardId);
- scene->_gameBoardSide[3]._outpostStation[1]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[1]);
-
- scene->_gameBoardSide[3]._outpostStation[2]._cardId = 7;
- scene->_gameBoardSide[3]._outpostStation[2]._card.postInit();
- scene->_gameBoardSide[3]._outpostStation[2]._card.setVisage(1332);
- scene->_gameBoardSide[3]._outpostStation[2]._card.setPosition(scene->_gameBoardSide[3]._outpostStation[2]._stationPos, 0);
- scene->_gameBoardSide[3]._outpostStation[2]._card.setStrip(2);
- scene->_gameBoardSide[3]._outpostStation[2]._card.setFrame(scene->_gameBoardSide[3]._outpostStation[2]._cardId);
- scene->_gameBoardSide[3]._outpostStation[2]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[3]._outpostStation[2]);
-
- scene->_gameBoardSide[0]._outpostStation[0]._cardId = 8;
- scene->_gameBoardSide[0]._outpostStation[0]._card.postInit();
- scene->_gameBoardSide[0]._outpostStation[0]._card.setVisage(1332);
- scene->_gameBoardSide[0]._outpostStation[0]._card.setPosition(scene->_gameBoardSide[0]._outpostStation[0]._stationPos, 0);
- scene->_gameBoardSide[0]._outpostStation[0]._card.setStrip(2);
- scene->_gameBoardSide[0]._outpostStation[0]._card.setFrame(scene->_gameBoardSide[0]._outpostStation[0]._cardId);
- scene->_gameBoardSide[0]._outpostStation[0]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[0]._outpostStation[0]);
-
- scene->_gameBoardSide[0]._outpostStation[1]._cardId = 9;
- scene->_gameBoardSide[0]._outpostStation[1]._card.postInit();
- scene->_gameBoardSide[0]._outpostStation[1]._card.setVisage(1332);
- scene->_gameBoardSide[0]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[0]._outpostStation[1]._stationPos, 0);
- scene->_gameBoardSide[0]._outpostStation[1]._card.setStrip(2);
- scene->_gameBoardSide[0]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[0]._outpostStation[1]._cardId);
- scene->_gameBoardSide[0]._outpostStation[1]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[0]._outpostStation[1]);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(60);
- scene->actionDisplay(1331, 9, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- scene->_gameBoardSide[2]._outpostStation[1]._cardId = 2;
- scene->_gameBoardSide[2]._outpostStation[1]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[1]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[1]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[1]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[1]._cardId);
- scene->_gameBoardSide[2]._outpostStation[1]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
-
- scene->_gameBoardSide[2]._outpostStation[2]._cardId = 3;
- scene->_gameBoardSide[2]._outpostStation[2]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[2]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[2]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[2]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[2]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[2]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[2]._cardId);
- scene->_gameBoardSide[2]._outpostStation[2]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[2]);
-
- scene->_gameBoardSide[2]._outpostStation[3]._cardId = 5;
- scene->_gameBoardSide[2]._outpostStation[3]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[3]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[3]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[3]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[3]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[3]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[3]._cardId);
- scene->_gameBoardSide[2]._outpostStation[3]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[3]);
-
- scene->_gameBoardSide[2]._outpostStation[4]._cardId = 6;
- scene->_gameBoardSide[2]._outpostStation[4]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[4]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[4]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[4]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[4]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[4]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[4]._cardId);
- scene->_gameBoardSide[2]._outpostStation[4]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[4]);
-
- scene->_gameBoardSide[2]._outpostStation[5]._cardId = 7;
- scene->_gameBoardSide[2]._outpostStation[5]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[5]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[5]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[5]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[5]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[5]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[5]._cardId);
- scene->_gameBoardSide[2]._outpostStation[5]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[5]);
-
- scene->_gameBoardSide[2]._outpostStation[6]._cardId = 8;
- scene->_gameBoardSide[2]._outpostStation[6]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[6]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[6]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[6]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[6]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[6]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[6]._cardId);
- scene->_gameBoardSide[2]._outpostStation[6]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[6]);
-
- scene->_gameBoardSide[2]._outpostStation[7]._cardId = 9;
- scene->_gameBoardSide[2]._outpostStation[7]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[7]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[7]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[7]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[7]._card.setStrip(2);
- scene->_gameBoardSide[2]._outpostStation[7]._card.setFrame(scene->_gameBoardSide[2]._outpostStation[7]._cardId);
- scene->_gameBoardSide[2]._outpostStation[7]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[7]);
-
- scene->_aSound1.play(62);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(120);
- scene->_gameBoardSide[2]._outpostStation[0]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[1]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[2]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[3]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[4]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[5]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[6]._card.remove();
- scene->_gameBoardSide[2]._outpostStation[7]._card.remove();
-
- scene->_gameBoardSide[1]._outpostStation[0]._card.remove();
- scene->_gameBoardSide[1]._outpostStation[1]._card.remove();
-
- scene->_gameBoardSide[3]._outpostStation[0]._card.remove();
- scene->_gameBoardSide[3]._outpostStation[1]._card.remove();
- scene->_gameBoardSide[3]._outpostStation[2]._card.remove();
-
- scene->_gameBoardSide[0]._outpostStation[0]._card.remove();
- scene->_gameBoardSide[0]._outpostStation[1]._card.remove();
-
- scene->_stockPile.setup(1332, 5, 1);
- scene->_stockPile.setPosition(Common::Point(165, 95));
- scene->_stockPile.setPriority(110);
- scene->_stockPile._effect = EFFECT_SHADED;
- scene->_stockPile.show();
-
- scene->_gameBoardSide[1]._handCard[0]._card.postInit();
- scene->_gameBoardSide[1]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[1]._handCard[0]._card.setPosition(scene->_gameBoardSide[1]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[1]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[1]._handCard[0]._card.setFrame(4);
- scene->_gameBoardSide[1]._handCard[0]._card.fixPriority(170);
-
- scene->_gameBoardSide[1]._handCard[1]._card.postInit();
- scene->_gameBoardSide[1]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[1]._handCard[1]._card.setPosition(scene->_gameBoardSide[1]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[1]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[1]._handCard[1]._card.setFrame(4);
- scene->_gameBoardSide[1]._handCard[1]._card.fixPriority(170);
-
- scene->_gameBoardSide[1]._handCard[2]._card.postInit();
- scene->_gameBoardSide[1]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[1]._handCard[2]._card.setPosition(scene->_gameBoardSide[1]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[1]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[1]._handCard[2]._card.setFrame(4);
- scene->_gameBoardSide[1]._handCard[2]._card.fixPriority(170);
-
- scene->_gameBoardSide[2]._handCard[0]._cardId = 30;
- scene->_gameBoardSide[2]._handCard[0]._card.postInit();
- scene->_gameBoardSide[2]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[0]._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[2]._handCard[0]._card.setFrame(2);
- scene->_gameBoardSide[2]._handCard[0]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[0]);
-
- scene->_gameBoardSide[2]._handCard[1]._cardId = 16;
- scene->_gameBoardSide[2]._handCard[1]._card.postInit();
- scene->_gameBoardSide[2]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[1]._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[2]._handCard[1]._card.setFrame(2);
- scene->_gameBoardSide[2]._handCard[1]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[1]);
-
- scene->_gameBoardSide[2]._handCard[2]._cardId = 1;
- scene->_gameBoardSide[2]._handCard[2]._card.postInit();
- scene->_gameBoardSide[2]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[2]._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[2]._handCard[2]._card.setFrame(2);
- scene->_gameBoardSide[2]._handCard[2]._card.fixPriority(170);
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[2]);
-
- scene->_gameBoardSide[3]._handCard[0]._card.postInit();
- scene->_gameBoardSide[3]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[3]._handCard[0]._card.setPosition(scene->_gameBoardSide[3]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[3]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[3]._handCard[0]._card.setFrame(3);
- scene->_gameBoardSide[3]._handCard[0]._card.fixPriority(170);
-
- scene->_gameBoardSide[3]._handCard[1]._card.postInit();
- scene->_gameBoardSide[3]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[3]._handCard[1]._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[3]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[3]._handCard[1]._card.setFrame(3);
- scene->_gameBoardSide[3]._handCard[1]._card.fixPriority(170);
-
- scene->_gameBoardSide[3]._handCard[2]._card.postInit();
- scene->_gameBoardSide[3]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[3]._handCard[2]._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[3]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[3]._handCard[2]._card.setFrame(3);
- scene->_gameBoardSide[3]._handCard[2]._card.fixPriority(170);
-
- scene->_gameBoardSide[0]._handCard[0]._card.postInit();
- scene->_gameBoardSide[0]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[0]._handCard[0]._card.setPosition(scene->_gameBoardSide[0]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[0]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[0]._handCard[0]._card.setFrame(2);
- scene->_gameBoardSide[0]._handCard[0]._card.fixPriority(170);
-
- scene->_gameBoardSide[0]._handCard[1]._card.postInit();
- scene->_gameBoardSide[0]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[0]._handCard[1]._card.setPosition(scene->_gameBoardSide[0]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[0]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[0]._handCard[1]._card.setFrame(2);
- scene->_gameBoardSide[0]._handCard[1]._card.fixPriority(170);
-
- scene->_gameBoardSide[0]._handCard[2]._card.postInit();
- scene->_gameBoardSide[0]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[0]._handCard[2]._card.setPosition(scene->_gameBoardSide[0]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[0]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[0]._handCard[2]._card.setFrame(2);
- scene->_gameBoardSide[0]._handCard[2]._card.fixPriority(170);
-
- R2_GLOBALS._sceneObjects->draw();
-
- scene->actionDisplay(1331, 10, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
- scene->_animatedCard._card.show();
- scene->_aSound2.play(61);
-
- Common::Point pt(91, 174);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
- }
- break;
- case 2: {
- scene->_gameBoardSide[2]._handCard[3]._cardId = 2;
- scene->_gameBoardSide[2]._handCard[3]._card.postInit();
- scene->_gameBoardSide[2]._handCard[3]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[3]._card.setPosition(scene->_gameBoardSide[2]._handCard[3]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[3]._card.setStrip(1);
- scene->_gameBoardSide[2]._handCard[3]._card.setFrame(2);
- scene->_gameBoardSide[2]._handCard[3]._card.fixPriority(170);
-
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._handCard[3]);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(60);
- scene->actionDisplay(1331, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->actionDisplay(1331, 12, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- scene->_gameBoardSide[2]._outpostStation[1]._cardId = 1;
- scene->_gameBoardSide[2]._outpostStation[1]._card.postInit();
- scene->_gameBoardSide[2]._outpostStation[1]._card.setVisage(1332);
- scene->_gameBoardSide[2]._outpostStation[1]._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
- scene->_gameBoardSide[2]._outpostStation[1]._card.hide();
-
- scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[2]._card._strip);
- scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._card._frame);
- scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
-
- scene->_gameBoardSide[2]._handCard[2]._cardId = 0;
- scene->_gameBoardSide[2]._handCard[2]._card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._outpostStation[1]._stationPos, this);
- }
- break;
- case 3: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
- scene->_aSound1.play(59);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(60);
- scene->actionDisplay(1331, 13, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- scene->_gameBoardSide[2]._outpostStation[1]._cardId = scene->_gameBoardSide[2]._handCard[3]._cardId;
-
- scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[3]._card._strip);
- scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[3]._card._frame);
-
- scene->_gameBoardSide[2]._handCard[3]._cardId = 0;
- scene->_gameBoardSide[2]._handCard[3]._card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[3]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._outpostStation[1]._stationPos, this);
- }
- break;
- case 4: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._outpostStation[1]);
- scene->_aSound1.play(59);
-
- scene->_discardPile._cardId = 1;
- scene->_discardPile._card.hide();
-
- scene->_animatedCard._card.setStrip(5);
- scene->_animatedCard._card.setFrame(1);
- scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._outpostStation[1]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
- }
- break;
- case 5: {
- scene->_animatedCard._card.hide();
-
- scene->_discardPile._card.postInit();
- scene->_discardPile._card.setVisage(1332);
- scene->_discardPile._card.setPosition(scene->_discardPile._stationPos, 0);
- scene->setAnimationInfo(&scene->_discardPile);
- scene->_aSound2.play(61);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(60);
- scene->actionDisplay(1331, 14, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- scene->_gameBoardSide[2]._delayCard._card.postInit();
- scene->_gameBoardSide[2]._delayCard._card.setVisage(1332);
- scene->_gameBoardSide[2]._delayCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
- scene->_gameBoardSide[2]._delayCard._card.hide();
-
- scene->_gameBoardSide[3]._handCard[2]._cardId = 0;
- scene->_gameBoardSide[3]._handCard[2].remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayCard._stationPos, this);
- }
- break;
- case 6: {
- scene->_animatedCard._card.hide();
- scene->_gameBoardSide[2]._delayCard._cardId = 21;
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._delayCard);
- scene->_aSound1.play(57);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(60);
- scene->actionDisplay(1331, 15, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- int tmpVal = 15;
- int i = -1;
-
- for (i = 0; i <= 7; i++) {
- tmpVal += 29;
-
- scene->_upperDisplayCard[i].postInit();
- scene->_upperDisplayCard[i].setVisage(1332);
- scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 90), 0);
- scene->_upperDisplayCard[i].setStrip(3);
- scene->_upperDisplayCard[i].fixPriority(190);
-
- scene->_lowerDisplayCard[i].postInit();
- scene->_lowerDisplayCard[i].setVisage(1332);
- scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 90), 0);
- scene->_lowerDisplayCard[i].setStrip(7);
- scene->_lowerDisplayCard[i].setFrame(1);
- scene->_lowerDisplayCard[i].fixPriority(180);
- }
-
- scene->_upperDisplayCard[0].setFrame(1);
- scene->_upperDisplayCard[1].setFrame(3);
- scene->_upperDisplayCard[2].setFrame(6);
- scene->_upperDisplayCard[3].setFrame(8);
- scene->_upperDisplayCard[4].setFrame(9);
- scene->_upperDisplayCard[5].setFrame(10);
- scene->_upperDisplayCard[6].setFrame(11);
- scene->_upperDisplayCard[7].setFrame(12);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(240);
-
- scene->_upperDisplayCard[0].remove();
- scene->_upperDisplayCard[1].remove();
- scene->_upperDisplayCard[2].remove();
- scene->_upperDisplayCard[3].remove();
- scene->_upperDisplayCard[4].remove();
- scene->_upperDisplayCard[5].remove();
- scene->_upperDisplayCard[6].remove();
- scene->_upperDisplayCard[7].remove();
-
- scene->_lowerDisplayCard[0].remove();
- scene->_lowerDisplayCard[1].remove();
- scene->_lowerDisplayCard[2].remove();
- scene->_lowerDisplayCard[3].remove();
- scene->_lowerDisplayCard[4].remove();
- scene->_lowerDisplayCard[5].remove();
- scene->_lowerDisplayCard[6].remove();
- scene->_lowerDisplayCard[7].remove();
-
- scene->_discardPile._cardId = scene->_gameBoardSide[2]._delayCard._cardId;
-
- scene->_gameBoardSide[2]._delayCard._cardId = 0;
- scene->_gameBoardSide[2]._delayCard._card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
- }
- break;
- case 7: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_discardPile);
- scene->_aSound2.play(61);
-
- R2_GLOBALS._sceneObjects->draw();
-
- scene->_gameBoardSide[2]._delayCard._card.postInit();
- scene->_gameBoardSide[2]._delayCard._card.setVisage(1332);
- scene->_gameBoardSide[2]._delayCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
- scene->_gameBoardSide[2]._delayCard._card.hide();
-
- scene->_gameBoardSide[3]._handCard[1]._cardId = 0;
- scene->_gameBoardSide[3]._handCard[1].remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayCard._stationPos, this);
- }
- break;
- case 8: {
- scene->_animatedCard._card.hide();
- scene->_gameBoardSide[2]._delayCard._cardId = 14;
- scene->setAnimationInfo(&scene->_gameBoardSide[2]._delayCard);
- scene->_aSound1.play(57);
-
- R2_GLOBALS._sceneObjects->draw();
-
- scene->actionDisplay(1331, 16, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- int tmpVal = 72;
- int i = -1;
-
- for (i = 0; i <= 3; i++) {
- tmpVal += 29;
- scene->_upperDisplayCard[i].postInit();
- scene->_upperDisplayCard[i].setVisage(1332);
- scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 71), 0);
- scene->_upperDisplayCard[i].setStrip(3);
- scene->_upperDisplayCard[i].fixPriority(190);
-
- scene->_lowerDisplayCard[i].postInit();
- scene->_lowerDisplayCard[i].setVisage(1332);
- scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 71), 0);
- scene->_lowerDisplayCard[i].setStrip(7);
- scene->_lowerDisplayCard[i].setFrame(1);
- scene->_lowerDisplayCard[i].fixPriority(180);
- }
-
- scene->_upperDisplayCard[0].setFrame(2);
- scene->_upperDisplayCard[1].setFrame(5);
- scene->_upperDisplayCard[2].setFrame(7);
- scene->_upperDisplayCard[3].setFrame(15);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(240);
- scene->actionDisplay(1331, 17, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- tmpVal = 72;
- for (i = 4; i <= 7; i++) {
- tmpVal += 29;
-
- scene->_upperDisplayCard[i].postInit();
- scene->_upperDisplayCard[i].setVisage(1332);
- scene->_upperDisplayCard[i].setPosition(Common::Point(tmpVal, 100), 0);
- scene->_upperDisplayCard[i].setStrip(4);
- scene->_upperDisplayCard[i].fixPriority(190);
-
- scene->_lowerDisplayCard[i].postInit();
- scene->_lowerDisplayCard[i].setVisage(1332);
- scene->_lowerDisplayCard[i].setPosition(Common::Point(tmpVal, 100), 0);
- scene->_lowerDisplayCard[i].setStrip(7);
- scene->_lowerDisplayCard[i].setFrame(1);
- scene->_lowerDisplayCard[i].fixPriority(180);
- }
-
- scene->_upperDisplayCard[4].setFrame(1);
- scene->_upperDisplayCard[5].setFrame(5);
- scene->_upperDisplayCard[6].setFrame(7);
- scene->_upperDisplayCard[7].setFrame(3);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(240);
-
- scene->_upperDisplayCard[0].remove();
- scene->_upperDisplayCard[1].remove();
- scene->_upperDisplayCard[2].remove();
- scene->_upperDisplayCard[3].remove();
- scene->_upperDisplayCard[4].remove();
- scene->_upperDisplayCard[5].remove();
- scene->_upperDisplayCard[6].remove();
- scene->_upperDisplayCard[7].remove();
-
- scene->_lowerDisplayCard[0].remove();
- scene->_lowerDisplayCard[1].remove();
- scene->_lowerDisplayCard[2].remove();
- scene->_lowerDisplayCard[3].remove();
- scene->_lowerDisplayCard[4].remove();
- scene->_lowerDisplayCard[5].remove();
- scene->_lowerDisplayCard[6].remove();
- scene->_lowerDisplayCard[7].remove();
-
- scene->_discardPile._cardId = scene->_gameBoardSide[2]._handCard[0]._cardId;
-
- scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[0]._card._strip);
- scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._card._frame);
- scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
-
- scene->_gameBoardSide[2]._handCard[0]._cardId = 0;
- scene->_gameBoardSide[2]._handCard[0]._card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[2]._delayCard._stationPos, this);
- }
- break;
- case 9: {
- scene->_aSound1.play(58);
- scene->_gameBoardSide[2]._delayCard._cardId = 0;
- scene->_gameBoardSide[2]._delayCard.remove();
- scene->_animatedCard._card.setStrip(5);
- scene->_animatedCard._card.setFrame(1);
- scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._delayCard._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
- }
- break;
- case 10: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_discardPile);
- scene->_aSound2.play(61);
-
- R2_GLOBALS._sceneObjects->draw();
- scene->actionDisplay(1331, 18, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- scene->_upperDisplayCard[0].postInit();
- scene->_upperDisplayCard[0].setVisage(1332);
- scene->_upperDisplayCard[0].setPosition(Common::Point(131, 71), 0);
- scene->_upperDisplayCard[0].fixPriority(190);
- scene->_upperDisplayCard[0].setStrip(3);
- scene->_upperDisplayCard[0].setFrame(4);
-
- scene->_lowerDisplayCard[0].postInit();
- scene->_lowerDisplayCard[0].setVisage(1332);
- scene->_lowerDisplayCard[0].setPosition(Common::Point(131, 71), 0);
- scene->_lowerDisplayCard[0].setStrip(7);
- scene->_lowerDisplayCard[0].setFrame(1);
- scene->_lowerDisplayCard[0].fixPriority(180);
-
- scene->_upperDisplayCard[1].postInit();
- scene->_upperDisplayCard[1].setVisage(1332);
- scene->_upperDisplayCard[1].setPosition(Common::Point(160, 71), 0);
- scene->_upperDisplayCard[1].fixPriority(190);
- scene->_upperDisplayCard[1].setStrip(3);
- scene->_upperDisplayCard[1].setFrame(16);
-
- scene->_lowerDisplayCard[1].postInit();
- scene->_lowerDisplayCard[1].setVisage(1332);
- scene->_lowerDisplayCard[1].setPosition(Common::Point(160, 71), 0);
- scene->_lowerDisplayCard[1].setStrip(7);
- scene->_lowerDisplayCard[1].setFrame(1);
- scene->_lowerDisplayCard[1].fixPriority(180);
-
- scene->_upperDisplayCard[2].postInit();
- scene->_upperDisplayCard[2].setVisage(1332);
- scene->_upperDisplayCard[2].setPosition(Common::Point(131, 100), 0);
- scene->_upperDisplayCard[2].fixPriority(190);
- scene->_upperDisplayCard[2].setStrip(4);
- scene->_upperDisplayCard[2].setFrame(4);
-
- scene->_lowerDisplayCard[2].postInit();
- scene->_lowerDisplayCard[2].setVisage(1332);
- scene->_lowerDisplayCard[2].setPosition(Common::Point(131, 100), 0);
- scene->_lowerDisplayCard[2].setStrip(7);
- scene->_lowerDisplayCard[2].setFrame(1);
- scene->_lowerDisplayCard[2].fixPriority(180);
-
- scene->_upperDisplayCard[3].postInit();
- scene->_upperDisplayCard[3].setVisage(1332);
- scene->_upperDisplayCard[3].setPosition(Common::Point(160, 100), 0);
- scene->_upperDisplayCard[3].fixPriority(190);
- scene->_upperDisplayCard[3].setStrip(4);
- scene->_upperDisplayCard[3].setFrame(2);
-
- scene->_lowerDisplayCard[3].postInit();
- scene->_lowerDisplayCard[3].setVisage(1332);
- scene->_lowerDisplayCard[3].setPosition(Common::Point(160, 100), 0);
- scene->_lowerDisplayCard[3].setStrip(7);
- scene->_lowerDisplayCard[3].setFrame(1);
- scene->_lowerDisplayCard[3].fixPriority(180);
-
- R2_GLOBALS._sceneObjects->draw();
-
- waitFrames(240);
-
- scene->_upperDisplayCard[0].remove();
- scene->_upperDisplayCard[1].remove();
- scene->_upperDisplayCard[2].remove();
- scene->_upperDisplayCard[3].remove();
-
- scene->_lowerDisplayCard[0].remove();
- scene->_lowerDisplayCard[1].remove();
- scene->_lowerDisplayCard[2].remove();
- scene->_lowerDisplayCard[3].remove();
-
- scene->_currentPlayerArrow.setFrame(1);
- scene->_currentPlayerArrow.show();
- scene->_currentPlayerArrow.animate(ANIM_MODE_2, NULL);
-
- R2_GLOBALS._sceneObjects->draw();
-
- scene->actionDisplay(1331, 19, 159, 10, 1, 220, 0, 7, 0, 154, 154);
-
- scene->_currentPlayerArrow.hide();
-
- scene->actionDisplay(1331, 20, 159, 10, 1, 220, 0, 7, 0, 154, 154);
- scene->actionDisplay(1331, 21, 159, 10, 1, 220, 0, 7, 0, 154, 154);
-
- scene->_discardPile._cardId = scene->_gameBoardSide[2]._handCard[1]._cardId;
-
- scene->_animatedCard._card.setStrip(scene->_gameBoardSide[2]._handCard[1]._card._strip);
- scene->_animatedCard._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._card._frame);
- scene->_animatedCard._card.animate(ANIM_MODE_NONE, NULL);
-
- scene->_gameBoardSide[2]._handCard[1]._cardId = 0;
- scene->_gameBoardSide[2]._handCard[1]._card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_discardPile._stationPos, this);
- }
- break;
- case 11: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_discardPile);
- scene->_aSound2.play(61);
- scene->_animatedCard._card.setStrip(5);
- scene->_animatedCard._card.setFrame(1);
- scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
-
- R2_GLOBALS._sceneObjects->draw();
-
- scene->actionDisplay(1331, 22, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- int i = -1;
- for (i = 0; i <= 3; i ++) {
- scene->_gameBoardSide[3]._handCard[i]._cardId = 0;
- scene->_gameBoardSide[3]._handCard[i]._card.remove();
-
- scene->_gameBoardSide[2]._handCard[i]._cardId = 0;
- scene->_gameBoardSide[2]._handCard[i]._card.remove();
-
- scene->_gameBoardSide[0]._handCard[i]._cardId = 0;
- scene->_gameBoardSide[0]._handCard[i]._card.remove();
-
- scene->_gameBoardSide[1]._handCard[i]._cardId = 0;
- scene->_gameBoardSide[1]._handCard[i]._card.remove();
- }
-
- for (i = 0; i <= 7; i++) {
- scene->_gameBoardSide[3]._outpostStation[i]._cardId = 0;
- scene->_gameBoardSide[3]._outpostStation[i]._card.remove();
-
- scene->_gameBoardSide[2]._outpostStation[i]._cardId = 0;
- scene->_gameBoardSide[2]._outpostStation[i]._card.remove();
-
- scene->_gameBoardSide[0]._outpostStation[i]._cardId = 0;
- scene->_gameBoardSide[0]._outpostStation[i]._card.remove();
-
- scene->_gameBoardSide[1]._outpostStation[i]._cardId = 0;
- scene->_gameBoardSide[1]._outpostStation[i]._card.remove();
- }
-
- scene->_gameBoardSide[2]._delayCard._cardId = 0;
- scene->_gameBoardSide[2]._delayCard._card.remove();
-
- scene->_discardPile._cardId = 0;
- scene->_discardPile._card.remove();
-
- scene->_stockPile.remove();
- }
- // No break on purpose
- case 0:
- R2_GLOBALS._sceneObjects->draw();
- signal();
- break;
- case 12:
- scene->suggestInstructions();
- remove();
- break;
- default:
- break;
- }
-}
-
-/**
- * Shuffle cards animation
- */
-void Scene1337::Action2::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0:
- scene->_shuffleAnimation._card.postInit();
- scene->_shuffleAnimation._card.setVisage(1332);
- scene->_shuffleAnimation._card.setStrip(8);
- scene->_shuffleAnimation._card.setFrame(1);
- scene->_shuffleAnimation._card.fixPriority(300);
- scene->_shuffleAnimation._card.setPosition(Common::Point(156, 108));
-
- scene->_discardPile._card.remove();
- scene->_discardPile._cardId = 0;
-
- scene->_aSound1.play(60);
- scene->_shuffleAnimation._card.animate(ANIM_MODE_5, this);
- break;
- case 1:
- scene->_shuffleAnimation._card.setFrame(1);
-
- scene->_aSound1.play(60);
- scene->_shuffleAnimation._card.animate(ANIM_MODE_5, this);
- break;
- case 2: {
- Common::Point pt(156, 108);
- NpcMover *mover = new NpcMover();
- scene->_shuffleAnimation._card.addMover(mover, &pt, this);
- }
- break;
- case 3:
- scene->_shuffleAnimation._card.remove();
- scene->_stockPile.setup(1332, 5, 1);
- scene->_stockPile.setPosition(Common::Point(162, 95));
- scene->_stockPile.setPriority(110);
- scene->_stockPile._effect = EFFECT_SHADED;
- scene->_stockPile.show();
- scene->_shuffleEndedFl = true;
- break;
- default:
- break;
- }
-}
-
-/**
- * Deal cards
- */
-void Scene1337::Action3::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
-
- switch (_actionIndex++) {
- case 0: {
- scene->_animatedCard._card._moveDiff = Common::Point(30, 30);
- scene->_animatedCard._card.setVisage(1332);
- scene->_animatedCard._card.setStrip(5);
- scene->_animatedCard._card.setFrame(1);
- scene->_animatedCard._card.fixPriority(400);
- scene->_animatedCard._card.animate(ANIM_MODE_2, NULL);
- scene->_aSound2.play(61);
-
- Common::Point pt(283, 146);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_animatedCard._card.show();
- scene->_gameBoardSide[1]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 1: {
- scene->_gameBoardSide[1]._handCard[0]._card.postInit();
- scene->_gameBoardSide[1]._handCard[0]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[1]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[1]._handCard[0]._card.setPosition(scene->_gameBoardSide[1]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[1]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[1]._handCard[0]._card.setFrame(4);
- scene->_gameBoardSide[1]._handCard[0]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(10, 174);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[2]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 2: {
- scene->_gameBoardSide[2]._handCard[0]._card.postInit();
- scene->_gameBoardSide[2]._handCard[0]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[2]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[0]._card.setPosition(scene->_gameBoardSide[2]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[0]._card.fixPriority(170);
- if (scene->_gameBoardSide[2]._handCard[0]._cardId > 25) {
- scene->_gameBoardSide[2]._handCard[0]._card.setStrip(4);
- scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId - 25);
- } else if (scene->_gameBoardSide[2]._handCard[0]._cardId > 9) {
- scene->_gameBoardSide[2]._handCard[0]._card.setStrip(3);
- scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId - 9);
- } else {
- scene->_gameBoardSide[2]._handCard[0]._card.setStrip(2);
- scene->_gameBoardSide[2]._handCard[0]._card.setFrame(scene->_gameBoardSide[2]._handCard[0]._cardId);
- }
- scene->_aSound2.play(61);
-
- Common::Point pt(14, 14);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[3]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 3: {
- scene->_gameBoardSide[3]._handCard[0]._card.postInit();
- scene->_gameBoardSide[3]._handCard[0]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[3]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[3]._handCard[0]._card.setPosition(scene->_gameBoardSide[3]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[3]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[3]._handCard[0]._card.setFrame(3);
- scene->_gameBoardSide[3]._handCard[0]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(280, 5);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[0]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 4: {
- scene->_gameBoardSide[0]._handCard[0]._card.postInit();
- scene->_gameBoardSide[0]._handCard[0]._card._moveDiff = Common::Point(30,30);
- scene->_gameBoardSide[0]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[0]._handCard[0]._card.setPosition(scene->_gameBoardSide[0]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[0]._handCard[0]._card.setStrip(5);
- scene->_gameBoardSide[0]._handCard[0]._card.setFrame(1);
- scene->_gameBoardSide[0]._handCard[0]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(283, 124);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[1]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 5: {
- scene->_gameBoardSide[1]._handCard[1]._card.postInit();
- scene->_gameBoardSide[1]._handCard[1]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[1]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[1]._handCard[1]._card.setPosition(scene->_gameBoardSide[1]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[1]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[1]._handCard[1]._card.setFrame(4);
- scene->_gameBoardSide[1]._handCard[1]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(37, 174);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[2]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 6: {
- scene->_gameBoardSide[2]._handCard[1]._card.postInit();
- scene->_gameBoardSide[2]._handCard[1]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[2]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[1]._card.setPosition(scene->_gameBoardSide[2]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[1]._card.fixPriority(170);
-
- if (scene->_gameBoardSide[2]._handCard[1]._cardId > 25) {
- scene->_gameBoardSide[2]._handCard[1]._card.setStrip(4);
- scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId - 25);
- } else if (scene->_gameBoardSide[2]._handCard[1]._cardId > 9) {
- scene->_gameBoardSide[2]._handCard[1]._card.setStrip(3);
- scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId - 9);
- } else {
- scene->_gameBoardSide[2]._handCard[1]._card.setStrip(2);
- scene->_gameBoardSide[2]._handCard[1]._card.setFrame(scene->_gameBoardSide[2]._handCard[1]._cardId);
- }
-
- scene->_aSound2.play(61);
-
- Common::Point pt(14, 36);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[3]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 7: {
- scene->_gameBoardSide[3]._handCard[1]._card.postInit();
- scene->_gameBoardSide[3]._handCard[1]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[3]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[3]._handCard[1]._card.setPosition(scene->_gameBoardSide[3]._handCard[1]._stationPos);
- scene->_gameBoardSide[3]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[3]._handCard[1]._card.setFrame(3);
- scene->_gameBoardSide[3]._handCard[1]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(253, 5);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[0]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 8: {
- scene->_gameBoardSide[0]._handCard[1]._card.postInit();
- scene->_gameBoardSide[0]._handCard[1]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[0]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[0]._handCard[1]._card.setPosition(scene->_gameBoardSide[0]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[0]._handCard[1]._card.setStrip(5);
- scene->_gameBoardSide[0]._handCard[1]._card.setFrame(1);
- scene->_gameBoardSide[0]._handCard[1]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(283, 102);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[1]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 9: {
- scene->_gameBoardSide[1]._handCard[2]._card.postInit();
- scene->_gameBoardSide[1]._handCard[2]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[1]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[1]._handCard[2]._card.setPosition(scene->_gameBoardSide[1]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[1]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[1]._handCard[2]._card.setFrame(4);
- scene->_gameBoardSide[1]._handCard[2]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(64, 174);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[2]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 10: {
- scene->_gameBoardSide[2]._handCard[2]._card.postInit();
- scene->_gameBoardSide[2]._handCard[2]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[2]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[2]._handCard[2]._card.setPosition(scene->_gameBoardSide[2]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[2]._handCard[2]._card.fixPriority(170);
-
- if (scene->_gameBoardSide[2]._handCard[2]._cardId > 25) {
- scene->_gameBoardSide[2]._handCard[2]._card.setStrip(4);
- scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId - 25);
- } else if (scene->_gameBoardSide[2]._handCard[2]._cardId > 9) {
- scene->_gameBoardSide[2]._handCard[2]._card.setStrip(3);
- scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId - 9);
- } else {
- scene->_gameBoardSide[2]._handCard[2]._card.setStrip(2);
- scene->_gameBoardSide[2]._handCard[2]._card.setFrame(scene->_gameBoardSide[2]._handCard[2]._cardId);
- }
-
- scene->_aSound2.play(61);
-
- Common::Point pt(14, 58);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[3]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 11: {
- scene->_gameBoardSide[3]._handCard[2]._card.postInit();
- scene->_gameBoardSide[3]._handCard[2]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[3]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[3]._handCard[2]._card.setPosition(scene->_gameBoardSide[3]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[3]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[3]._handCard[2]._card.setFrame(3);
- scene->_gameBoardSide[3]._handCard[2]._card.fixPriority(170);
- scene->_aSound2.play(61);
-
- Common::Point pt(226, 5);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
-
- scene->_gameBoardSide[0]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- }
- break;
- case 12:
- scene->_gameBoardSide[0]._handCard[2]._card.postInit();
- scene->_gameBoardSide[0]._handCard[2]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[0]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[0]._handCard[2]._card.setPosition(scene->_gameBoardSide[0]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[0]._handCard[2]._card.setStrip(5);
- scene->_gameBoardSide[0]._handCard[2]._card.setFrame(1);
- scene->_gameBoardSide[0]._handCard[2]._card.fixPriority(170);
- scene->_animatedCard._card.hide();
- default:
- break;
- }
-
- if (_actionIndex > 12) {
- scene->_currentPlayerNumb = 0;
- R2_GLOBALS._sceneObjects->draw();
- scene->actionDisplay(1330, 0, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- scene->handleNextTurn();
- } else if (_actionIndex >= 1) {
- scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
- scene->_cardsAvailableNumb--;
- }
-}
-
-/**
- * Action used to handle the other players' turn
- */
-void Scene1337::Action4::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0:
- if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId == 0)
- && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
- if (scene->_cardsAvailableNumb < 0)
- scene->shuffleCards();
- scene->_animatedCard._card.setPosition(Common::Point(162, 95), 0);
- scene->_animatedCard._card.show();
- scene->_aSound2.play(61);
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card1Pos, this);
-
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
- scene->_cardsAvailableNumb--;
-
- if (scene->_cardsAvailableNumb < 0)
- scene->_stockPile.remove();
- } else {
- // Self call, forcing next actionIndex
- signal();
- }
- break;
- case 1:
- if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card1Pos.x)
- && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card1Pos.y) ) {
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.postInit();
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setVisage(1332);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._stationPos, 0);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setStrip(1);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._card.fixPriority(170);
- }
-
- if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
- scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]);
-
- scene->_animatedCard._card.hide();
- if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[0]._cardId == 0)
- && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
- if (scene->_cardsAvailableNumb < 0)
- scene->shuffleCards();
- scene->_animatedCard._card.setPosition(Common::Point(162, 95));
- scene->_animatedCard._card.show();
-
- scene->_aSound2.play(61);
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card2Pos, this);
-
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
- scene->_cardsAvailableNumb--;
- if (scene->_cardsAvailableNumb < 0)
- scene->_stockPile.remove();
- } else
- signal();
- break;
- case 2:
- if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card2Pos.x)
- && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card2Pos.y) ) {
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.postInit();
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setVisage(1332);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._stationPos, 0);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setStrip(1);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]._card.fixPriority(170);
- }
-
- if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
- scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[1]);
-
- scene->_animatedCard._card.hide();
- if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._cardId == 0)
- && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
- if (scene->_cardsAvailableNumb < 0)
- scene->shuffleCards();
- scene->_animatedCard._card.setPosition(Common::Point(162, 95));
- scene->_animatedCard._card.show();
-
- scene->_aSound2.play(61);
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card3Pos, this);
-
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
- scene->_cardsAvailableNumb--;
- if (scene->_cardsAvailableNumb < 0)
- scene->_stockPile.remove();
- } else
- signal();
- break;
- case 3:
- if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card3Pos.x)
- && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card3Pos.y) ) {
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.postInit();
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setVisage(1332);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._stationPos, 0);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setStrip(1);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]._card.fixPriority(170);
- }
-
- if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
- scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[2]);
-
- scene->_animatedCard._card.hide();
- if ( (scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._cardId == 0)
- && (!scene->isStationCard(scene->_gameBoardSide[scene->_currentPlayerNumb]._delayCard._cardId))) {
- if (scene->_cardsAvailableNumb < 0)
- scene->shuffleCards();
- scene->_animatedCard._card.setPosition(Common::Point(162, 95));
- scene->_animatedCard._card.show();
-
- scene->_aSound2.play(61);
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_gameBoardSide[scene->_currentPlayerNumb]._card4Pos, this);
-
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._cardId = scene->_availableCardsPile[scene->_cardsAvailableNumb];
- scene->_availableCardsPile[scene->_cardsAvailableNumb] = 0;
- scene->_cardsAvailableNumb--;
- if (scene->_cardsAvailableNumb < 0)
- scene->_stockPile.remove();
- } else
- signal();
- break;
- case 4:
- if ( (scene->_animatedCard._card._position.x == scene->_gameBoardSide[scene->_currentPlayerNumb]._card4Pos.x)
- && (scene->_animatedCard._card._position.y == scene->_gameBoardSide[scene->_currentPlayerNumb]._card4Pos.y) ) {
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.postInit();
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card._moveDiff = Common::Point(30, 30);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setVisage(1332);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setPosition(scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._stationPos, 0);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setStrip(1);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.setFrame(scene->_gameBoardSide[scene->_currentPlayerNumb]._frameNum);
- scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]._card.fixPriority(170);
- }
-
- if ((R2_GLOBALS._debugCardGame) || (scene->_currentPlayerNumb == 2))
- scene->setAnimationInfo(&scene->_gameBoardSide[scene->_currentPlayerNumb]._handCard[3]);
-
- scene->_animatedCard._card.hide();
- switch (scene->_currentPlayerNumb) {
- case 0:
- scene->handlePlayer0();
- break;
- case 1:
- scene->handlePlayer1();
- break;
- case 2:
- scene->handleAutoplayPlayer2();
- break;
- case 3:
- scene->handlePlayer3();
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-}
-
-/**
- * Animations for discarding a card
- */
-void Scene1337::Action5::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard1->_cardId;
- scene->_currentDiscardIndex--;
- if (!g_globals->_sceneObjects->contains(&scene->_discardPile._card)) {
- // The first discarded card makes the pile appear
- scene->_discardPile._card.postInit();
- scene->_discardPile._card.hide();
- scene->_discardPile._card.setVisage(1332);
- scene->_discardPile._card.setPosition(scene->_discardPile._stationPos, 0);
- scene->_discardPile._card.fixPriority(170);
- }
-
- scene->_discardPile._cardId = scene->_actionCard1->_cardId;
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
-
- if (scene->_actionCard1 == &scene->_selectedCard) {
- scene->setCursorData(5, 1, 4);
- scene->subC4CEC();
- }
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
- Common::Point pt(128, 95);
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &pt, this);
- }
- break;
- case 1:
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(&scene->_discardPile);
- scene->_aSound2.play(61);
- scene->handleNextTurn();
- break;
- default:
- break;
- }
-}
-
-/**
- * Animations for playing a platform card
- */
-void Scene1337::Action6::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_actionCard2->_cardId = 1;
- scene->_actionCard2->_card.postInit();
- scene->_actionCard2->_card.hide();
- scene->_actionCard2->_card.setVisage(1332);
- scene->_actionCard2->_card.setPosition(scene->_actionCard2->_stationPos);
- scene->_actionCard2->_card.fixPriority(170);
-
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 1:
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(59);
- if (scene->_actionCard1 == &scene->_selectedCard) {
- scene->setCursorData(5, 1, 4);
- scene->subC4CEC();
- }
- scene->handleNextTurn();
- break;
- default:
- break;
- }
-}
-
-/**
- * Upgrade platform to station by playing a station card on top of it
- */
-void Scene1337::Action7::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
-
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 1:
- if (scene->_actionCard1 == &scene->_selectedCard) {
- scene->setCursorData(5, 1, 4);
- scene->subC4CEC();
- }
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(59);
- scene->_discardedPlatformCard._cardId = 1;
- scene->_discardedPlatformCard._stationPos = scene->_actionCard2->_stationPos;
- scene->_discardedPlatformCard._card.postInit();
- scene->_discardedPlatformCard._card.hide();
- scene->_discardedPlatformCard._card._flags = OBJFLAG_HIDING;
-
- scene->discardCard(&scene->_discardedPlatformCard);
- break;
- default:
- break;
- }
-}
-
-void Scene1337::Action8::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
- scene->_currentDiscardIndex--;
-
- scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
- scene->_actionCard1->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 1:
- scene->_animatedCard._card.hide();
-
- if (scene->_actionCard1 == &scene->_selectedCard) {
- scene->setCursorData(5, 1, 4);
- scene->subC4CEC();
- }
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(58);
- scene->discardCard(scene->_actionCard2);
- break;
- default:
- break;
- }
-}
-
-// Play delay card
-void Scene1337::Action9::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
- scene->_actionCard2->_card.postInit();
- scene->_actionCard2->_card.hide();
- scene->_actionCard2->_card.setVisage(1332);
- scene->_actionCard2->_card.setPosition(scene->_actionCard2->_stationPos, 0);
- scene->_actionCard2->_card.fixPriority(170);
-
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 1:
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(57);
-
- if (scene->_actionCard1 == &scene->_selectedCard) {
- scene->setCursorData(5, 1, 4);
- scene->subC4CEC();
- }
-
- scene->handleNextTurn();
- break;
- default:
- break;
- }
-}
-
-// Counter a trick with a card
-void Scene1337::Action10::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_actionCard3->_card.postInit();
- scene->_actionCard3->_card.hide();
- scene->_actionCard3->_card.setVisage(1332);
- scene->_actionCard3->_card.setPosition(scene->_actionCard3->_stationPos, 0);
- scene->_actionCard3->_card.fixPriority(170);
- scene->_actionCard3->_cardId = scene->_actionCard1->_cardId;
-
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
-
- if (scene->_actionCard1 == &scene->_selectedCard) {
- scene->setCursorData(5, 1, 4);
- scene->subC4CEC();
- }
-
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard3->_stationPos, this);
- }
- break;
- case 1: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(scene->_actionCard3);
- scene->_aSound1.play(57);
-
- bool found = false;
- int indexFound = -1;
-
- switch (scene->_actionIdx1) {
- case 0:
- for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_gameBoardSide[0]._handCard[indexFound]._cardId == 29) {
- found = true;
- break;
- }
- }
- break;
- case 1:
- for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_gameBoardSide[1]._handCard[indexFound]._cardId == 29) {
- found = true;
- break;
- }
- }
- break;
- case 2:
- for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_gameBoardSide[2]._handCard[indexFound]._cardId == 29) {
- found = true;
- break;
- }
- }
- break;
- case 3:
- for (indexFound = 0; indexFound < 3; indexFound++) {
- if (scene->_gameBoardSide[3]._handCard[indexFound]._cardId == 29) {
- found = true;
- break;
- }
- }
- break;
- default:
- break;
- }
-
- bool found2 = false;
-
- if (found) {
- switch (scene->_actionIdx1) {
- case 0:
- scene->subC51A0(&scene->_gameBoardSide[0]._handCard[indexFound], scene->_actionCard3);
- found2 = true;
- break;
- case 1:
- scene->subC51A0(&scene->_gameBoardSide[1]._handCard[indexFound], scene->_actionCard3);
- found2 = true;
- break;
- case 2:
- scene->subC4CD2();
- if (MessageDialog::show(USE_INTERCEPTOR, NO_MSG, YES_MSG) == 0)
- scene->subC4CEC();
- else {
- scene->subC51A0(&scene->_gameBoardSide[2]._handCard[indexFound], scene->_actionCard3);
- found2 = true;
- }
- break;
- case 3:
- scene->subC51A0(&scene->_gameBoardSide[3]._handCard[indexFound], scene->_actionCard3);
- found2 = true;
- break;
- default:
- break;
- }
- }
-
- if (!found2)
- break;
-
- if (scene->_actionIdx1 == 2) {
- int j = 0;
- for (int i = 0; i <= 7; i++) {
- if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)
- ++j;
- }
-
- if (j <= 1) {
- for (int i = 0; i <= 7; i++) {
- if (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0) {
- scene->_actionCard2 = &scene->_gameBoardSide[2]._outpostStation[i];
- break;
- }
- }
- } else {
- scene->subC4CD2();
-
- found2 = false;
- while (!found2) {
- scene->actionDisplay(1330, 130, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- // Wait for a mouse or keypress
- Event event;
- while (!g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !g_vm->shouldQuit()) {
- g_globals->_scenePalette.signalListeners();
- R2_GLOBALS._sceneObjects->draw();
- g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
- }
-
- scene->_selectedCard._stationPos = event.mousePos;
-
- for (int i = 0; i <= 7; i++) {
- if (scene->_gameBoardSide[2]._outpostStation[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[2]._outpostStation[i]._cardId != 0)) {
- scene->_actionCard2 = &scene->_gameBoardSide[2]._outpostStation[0];
- found2 = true;
- break;
- }
- }
- }
- scene->subC4CEC();
- }
- }
-
- scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
- scene->_currentDiscardIndex--;
- scene->_actionCard2->_cardId = 0;
- scene->_actionCard2->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard2->_stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard3->_stationPos, this);
- }
- break;
- case 2:
- scene->_animatedCard._card.hide();
- scene->discardCard(scene->_actionCard3);
- break;
- default:
- break;
- }
-}
-
-// Use trick (card #25 - thieft ?) and pick a card from the opponent
-void Scene1337::Action11::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_actionCard2->_card.postInit();
- scene->_actionCard2->_card.hide();
- scene->_actionCard2->_card.setVisage(1332);
- scene->_actionCard2->_card.setPosition(scene->_actionCard2->_stationPos, 0);
- scene->_actionCard2->_card.fixPriority(170);
- scene->_actionCard2->_cardId = 25;
-
- if (scene->_actionIdx1 == 2) {
- scene->_animatedCard._card.setPosition(scene->_actionCard2->_stationPos, 0);
- scene->setCursorData(5, 1, 4);
- } else {
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- }
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 1: {
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(57);
-
- bool found = false;
- bool noAction = true;
-
- int i = -1;
-
- switch (scene->_actionIdx2) {
- case 0:
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[0]._handCard[i]._cardId == 27) {
- found = true;
- break;
- }
- }
-
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
- scene->_actionCard1 = &scene->_gameBoardSide[0]._handCard[i];
- scene->_actionCard2 = &scene->_gameBoardSide[0]._emptyStationPos;
- if (scene->_actionIdx1 != 0) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
- }
- scene->_actionItem.setAction(&scene->_action12);
- noAction = false;
- }
- break;
- case 1:
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[1]._handCard[i]._cardId == 27) {
- found = true;
- break;
- }
- }
-
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
- scene->_actionCard1 = &scene->_gameBoardSide[1]._handCard[i];
- scene->_actionCard2 = &scene->_gameBoardSide[1]._emptyStationPos;
- if (scene->_actionIdx1 != 1) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
- }
- scene->_actionItem.setAction(&scene->_action12);
- noAction = false;
- }
- break;
- case 2:
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[2]._handCard[i]._cardId == 27) {
- found = true;
- break;
- }
- }
-
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
- scene->subC4CD2();
- if (MessageDialog::show(USE_DOUBLE_AGENT, NO_MSG, YES_MSG) == 0)
- scene->subC4CEC();
- else {
- scene->subC4CEC();
- scene->_actionCard1 = &scene->_gameBoardSide[2]._handCard[i];
- scene->_actionCard2 = &scene->_gameBoardSide[2]._emptyStationPos;
- if (scene->_actionIdx1 != 2) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
- }
- scene->_actionItem.setAction(&scene->_action12);
- noAction = false;
- }
- }
- break;
- case 3:
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[3]._handCard[i]._cardId == 27) {
- found = true;
- break;
- }
- }
-
- if ((found) && (scene->getFreeHandCard(scene->_actionIdx1) != -1)) {
- scene->_actionCard1 = &scene->_gameBoardSide[3]._handCard[i];
- scene->_actionCard2 = &scene->_gameBoardSide[3]._emptyStationPos;
- if (scene->_actionIdx1 != 3) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx1);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx1]._handCard[tmpVal];
- }
- scene->_actionItem.setAction(&scene->_action12);
- noAction = false;
- }
- break;
- default:
- break;
- }
-
- if (!noAction)
- return;
-
- if (scene->_actionIdx1 == 2) {
- int count = 0;
- if (scene->_actionIdx2 != 2) {
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[scene->_actionIdx2]._handCard[i]._cardId == 0)
- ++count;
- }
- }
-
- if (count > 1) {
- scene->subC4CD2();
-
- found = false;
- while (!found) {
- switch (scene->_actionIdx2) {
- case 0:
- scene->actionDisplay(1330, 131, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 1:
- scene->actionDisplay(1330, 132, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 3:
- scene->actionDisplay(1330, 133, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
-
- Event event;
- while (!g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !g_vm->shouldQuit()) {
- g_globals->_scenePalette.signalListeners();
- R2_GLOBALS._sceneObjects->draw();
- g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
- }
-
- scene->_selectedCard._stationPos = event.mousePos;
-
- found = false;
-
- if (scene->_actionIdx2 != 2) {
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[scene->_actionIdx2]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[scene->_actionIdx2]._handCard[i]._cardId != 0)) {
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx2]._handCard[i];
- found = true;
- break;
- }
- }
- }
- } // while
- scene->_displayHelpFl = true;
- scene->subC4CEC();
- } else if (scene->_actionIdx2 != 2) {
- int tmpVal = scene->getFreeHandCard(scene->_actionIdx2);
- scene->_actionCard3 = &scene->_gameBoardSide[scene->_actionIdx2]._handCard[tmpVal];
- }
- }
-
- scene->_actionCard1->_card.postInit();
- scene->_actionCard1->_card.hide();
- scene->_actionCard1->_card.setVisage(1332);
- scene->_actionCard1->_card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_actionCard1->_card.fixPriority(170);
- scene->_actionCard1->_card.setStrip2(1);
- scene->_actionCard1->_cardId = scene->_actionCard3->_cardId;
-
- scene->_actionCard3->_cardId = 0;
- scene->_actionCard3->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard3->_stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard1->_stationPos, this);
- }
- break;
- case 2:
- scene->_animatedCard._card.hide();
- switch (scene->_actionIdx1) {
- case 0:
- scene->_actionCard1->_card.setFrame2(2);
- scene->_actionCard1->_card.show();
- break;
- case 1:
- scene->_actionCard1->_card.setFrame2(4);
- scene->_actionCard1->_card.show();
- break;
- case 3:
- scene->_actionCard1->_card.setFrame2(3);
- scene->_actionCard1->_card.show();
- break;
- default:
- scene->setAnimationInfo(scene->_actionCard1);
- break;
- }
-
- scene->_currentPlayerNumb--;
- scene->_showPlayerTurn = false;
- scene->discardCard(scene->_actionCard2);
- break;
- default:
- break;
- }
-}
-
-// Pick a card in opponent hand
-void Scene1337::Action12::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0:
- signal();
- break;
- case 1: {
- scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
- scene->_currentDiscardIndex++;
- scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 2:
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(58);
- if (scene->_actionIdx2 == 2) {
- int count = 0;
- int i = -1;
- switch (scene->_actionIdx1) {
- case 0:
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)
- ++count;
- }
- break;
- case 1:
- for (i = 0; i <= 3; i++) {
- // The original game was counting in the hand of player 3, which is obviously wrong
- if (scene->_gameBoardSide[1]._handCard[i]._cardId != 0)
- ++count;
- }
- break;
- case 3:
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)
- ++count;
- }
- break;
- default:
- break;
- }
-
- if (count > 1) {
- scene->subC4CD2();
-
- bool found = false;
-
- while (!found) {
- switch (scene->_actionIdx1) {
- case 0:
- scene->actionDisplay(1330, 131, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 1:
- scene->actionDisplay(1330, 132, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 3:
- scene->actionDisplay(1330, 133, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
-
- Event event;
- while (!g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !g_vm->shouldQuit()) {
- g_globals->_scenePalette.signalListeners();
- R2_GLOBALS._sceneObjects->draw();
- g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
- }
-
- scene->_selectedCard._stationPos = event.mousePos;
-
- if (scene->_actionIdx1 == 0) {
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[0]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[0]._handCard[i]._cardId != 0)) {
- found = true;
- scene->_actionCard3 = &scene->_gameBoardSide[0]._handCard[i];
- break;
- }
- }
- }
-
- if (scene->_actionIdx1 == 3) {
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[3]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[3]._handCard[i]._cardId != 0)) {
- found = true;
- scene->_actionCard3 = &scene->_gameBoardSide[3]._handCard[i];
- break;
- }
- }
- }
-
- if (scene->_actionIdx1 == 1) {
- for (i = 0; i <= 3; i++) {
- if (scene->_gameBoardSide[1]._handCard[i].isIn(scene->_selectedCard._stationPos) && (scene->_gameBoardSide[1]._handCard[i]._cardId != 0)) {
- found = true;
- scene->_actionCard3 = &scene->_gameBoardSide[1]._handCard[i];
- break;
- }
- }
- }
- }
- scene->subC4CEC();
- } else if (scene->_actionIdx1 != 1) {
- switch (scene->_actionIdx1) {
- case 0:
- scene->_actionCard3 = &scene->_gameBoardSide[0]._handCard[scene->getFreeHandCard(0)];
- break;
- case 3:
- scene->_actionCard3 = &scene->_gameBoardSide[3]._handCard[scene->getFreeHandCard(3)];
- break;
- default:
- break;
- }
- } else {
- scene->_actionCard3 = &scene->_gameBoardSide[1]._handCard[scene->getFreeHandCard(1)];
- }
-
- scene->_actionCard1->_card.postInit();
- scene->_actionCard1->_card.hide();
- scene->_actionCard1->_card.setVisage(1332);
- scene->_actionCard1->_card.setPosition(scene->_actionCard1->_stationPos);
- scene->_actionCard1->_card.fixPriority(170);
- scene->_actionCard1->_card.setStrip2(1);
- scene->_actionCard1->_cardId = scene->_actionCard3->_cardId;
-
- scene->_actionCard3->_cardId = 0;
- scene->_actionCard3->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard3->_stationPos);
- scene->_animatedCard._card.show();
- scene->_aSound1.play(57);
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard1->_stationPos, this);
- }
- break;
- case 3:
- scene->_animatedCard._card.hide();
- switch (scene->_actionIdx2) {
- case 0:
- scene->_actionCard1->_card.setFrame2(2);
- scene->_actionCard1->_card.show();
- break;
- case 1:
- scene->_actionCard1->_card.setFrame2(4);
- scene->_actionCard1->_card.show();
- break;
- case 3:
- scene->_actionCard1->_card.setFrame2(3);
- scene->_actionCard1->_card.show();
- break;
- default:
- scene->setAnimationInfo(scene->_actionCard1);
- break;
- }
- scene->discardCard(scene->_actionCard2);
- scene->handleNextTurn();
- break;
- default:
- break;
- }
-}
-
-void Scene1337::Action13::signal() {
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_actionIndex++) {
- case 0: {
- scene->_availableCardsPile[scene->_currentDiscardIndex] = scene->_actionCard2->_cardId;
- scene->_currentDiscardIndex--;
-
- scene->_actionCard2->_cardId = scene->_actionCard1->_cardId;
-
- scene->_actionCard1->_cardId = 0;
- scene->_actionCard1->_card.remove();
-
- scene->_animatedCard._card.setPosition(scene->_actionCard1->_stationPos, 0);
- scene->_animatedCard._card.show();
-
- NpcMover *mover = new NpcMover();
- scene->_animatedCard._card.addMover(mover, &scene->_actionCard2->_stationPos, this);
- }
- break;
- case 1:
- scene->_animatedCard._card.hide();
- scene->setAnimationInfo(scene->_actionCard2);
- scene->_aSound1.play(58);
- signal();
- break;
- case 2:
- scene->discardCard(scene->_actionCard2);
- break;
- default:
- break;
- }
-}
-
-void Scene1337::postInit(SceneObjectList *OwnerList) {
-// In the original, may be found in subPostInit.
-// Without it, enableControl asserts
- loadScene(1330);
- R2_GLOBALS._uiElements._active = false;
- SceneExt::postInit();
-//
-
- // Hide the user interface
- BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
- R2_GLOBALS._uiElements._visible = false;
-
- R2_GLOBALS._player.enableControl();
- R2_GLOBALS._player._canWalk = false;
- R2_GLOBALS._player._uiEnabled = false;
-
- _delayedFunction = nullptr;
-
- _actionCard1 = nullptr;
- _actionCard2 = nullptr;
- _actionCard3 = nullptr;
-
- _gameBoardSide[2]._handCard[0]._stationPos = Common::Point(10, 174);
- _gameBoardSide[2]._handCard[1]._stationPos = Common::Point(37, 174);
- _gameBoardSide[2]._handCard[2]._stationPos = Common::Point(64, 174);
- _gameBoardSide[2]._handCard[3]._stationPos = Common::Point(91, 174);
-
- _gameBoardSide[2]._outpostStation[0]._stationPos = Common::Point(119, 174);
- _gameBoardSide[2]._outpostStation[1]._stationPos = Common::Point(119, 148);
- _gameBoardSide[2]._outpostStation[2]._stationPos = Common::Point(119, 122);
- _gameBoardSide[2]._outpostStation[3]._stationPos = Common::Point(145, 122);
- _gameBoardSide[2]._outpostStation[4]._stationPos = Common::Point(171, 122);
- _gameBoardSide[2]._outpostStation[5]._stationPos = Common::Point(171, 148);
- _gameBoardSide[2]._outpostStation[6]._stationPos = Common::Point(171, 174);
- _gameBoardSide[2]._outpostStation[7]._stationPos = Common::Point(145, 174);
-
- _gameBoardSide[2]._delayCard._stationPos = Common::Point(199, 174);
-
- _gameBoardSide[2]._emptyStationPos._stationPos = Common::Point(145, 148);
-
- _gameBoardSide[2]._card1Pos = Common::Point(10, 174);
- _gameBoardSide[2]._card2Pos = Common::Point(37, 174);
- _gameBoardSide[2]._card3Pos = Common::Point(64, 174);
- _gameBoardSide[2]._card4Pos = Common::Point(91, 174);
- _gameBoardSide[2]._frameNum = 2;
-
- _gameBoardSide[3]._handCard[0]._stationPos = Common::Point(14, 14);
- _gameBoardSide[3]._handCard[1]._stationPos = Common::Point(14, 36);
- _gameBoardSide[3]._handCard[2]._stationPos = Common::Point(14, 58);
- _gameBoardSide[3]._handCard[3]._stationPos = Common::Point(14, 80);
-
- _gameBoardSide[3]._outpostStation[0]._stationPos = Common::Point(37, 66);
- _gameBoardSide[3]._outpostStation[1]._stationPos = Common::Point(63, 66);
- _gameBoardSide[3]._outpostStation[2]._stationPos = Common::Point(89, 66);
- _gameBoardSide[3]._outpostStation[3]._stationPos = Common::Point(89, 92);
- _gameBoardSide[3]._outpostStation[4]._stationPos = Common::Point(89, 118);
- _gameBoardSide[3]._outpostStation[5]._stationPos = Common::Point(63, 118);
- _gameBoardSide[3]._outpostStation[6]._stationPos = Common::Point(37, 118);
- _gameBoardSide[3]._outpostStation[7]._stationPos = Common::Point(37, 92);
-
- _gameBoardSide[3]._delayCard._stationPos = Common::Point(37, 145);
-
- _gameBoardSide[3]._emptyStationPos._stationPos = Common::Point(63, 92);
-
- _gameBoardSide[3]._card1Pos = Common::Point(14, 14);
- _gameBoardSide[3]._card2Pos = Common::Point(14, 36);
- _gameBoardSide[3]._card3Pos = Common::Point(14, 58);
- _gameBoardSide[3]._card4Pos = Common::Point(14, 80);
- _gameBoardSide[3]._frameNum = 3;
-
- _gameBoardSide[0]._handCard[0]._stationPos = Common::Point(280, 5);
- _gameBoardSide[0]._handCard[1]._stationPos = Common::Point(253, 5);
- _gameBoardSide[0]._handCard[2]._stationPos = Common::Point(226, 5);
- _gameBoardSide[0]._handCard[3]._stationPos = Common::Point(199, 5);
-
- _gameBoardSide[0]._outpostStation[0]._stationPos = Common::Point(171, 16);
- _gameBoardSide[0]._outpostStation[1]._stationPos = Common::Point(171, 42);
- _gameBoardSide[0]._outpostStation[2]._stationPos = Common::Point(171, 68);
- _gameBoardSide[0]._outpostStation[3]._stationPos = Common::Point(145, 68);
- _gameBoardSide[0]._outpostStation[4]._stationPos = Common::Point(119, 68);
- _gameBoardSide[0]._outpostStation[5]._stationPos = Common::Point(119, 42);
- _gameBoardSide[0]._outpostStation[6]._stationPos = Common::Point(119, 16);
- _gameBoardSide[0]._outpostStation[7]._stationPos = Common::Point(145, 16);
-
- _gameBoardSide[0]._delayCard._stationPos = Common::Point(91, 16);
-
- _gameBoardSide[0]._emptyStationPos._stationPos = Common::Point(145, 42);
-
- _gameBoardSide[0]._card1Pos = Common::Point(280, 5);
- _gameBoardSide[0]._card2Pos = Common::Point(253, 5);
- _gameBoardSide[0]._card3Pos = Common::Point(226, 5);
- _gameBoardSide[0]._card4Pos = Common::Point(199, 5);
- _gameBoardSide[0]._frameNum = 2;
-
- _gameBoardSide[1]._handCard[0]._stationPos = Common::Point(283, 146);
- _gameBoardSide[1]._handCard[1]._stationPos = Common::Point(283, 124);
- _gameBoardSide[1]._handCard[2]._stationPos = Common::Point(283, 102);
- _gameBoardSide[1]._handCard[3]._stationPos = Common::Point(283, 80);
-
- _gameBoardSide[1]._outpostStation[0]._stationPos = Common::Point(253, 122);
- _gameBoardSide[1]._outpostStation[1]._stationPos = Common::Point(227, 122);
- _gameBoardSide[1]._outpostStation[2]._stationPos = Common::Point(201, 122);
- _gameBoardSide[1]._outpostStation[3]._stationPos = Common::Point(201, 96);
- _gameBoardSide[1]._outpostStation[4]._stationPos = Common::Point(201, 70);
- _gameBoardSide[1]._outpostStation[5]._stationPos = Common::Point(227, 70);
- _gameBoardSide[1]._outpostStation[6]._stationPos = Common::Point(253, 70);
- _gameBoardSide[1]._outpostStation[7]._stationPos = Common::Point(253, 96);
-
- _gameBoardSide[1]._delayCard._stationPos = Common::Point(253, 43);
-
- _gameBoardSide[1]._emptyStationPos._stationPos = Common::Point(227, 96);
-
- _gameBoardSide[1]._card1Pos = Common::Point(283, 146);
- _gameBoardSide[1]._card2Pos = Common::Point(283, 124);
- _gameBoardSide[1]._card3Pos = Common::Point(283, 102);
- _gameBoardSide[1]._card4Pos = Common::Point(283, 80);
- _gameBoardSide[1]._frameNum = 4;
-
- subPostInit();
-
- _stockPile.postInit();
-}
-
-void Scene1337::remove() {
- if (R2_GLOBALS._v57709 > 1) {
- subD1917();
- subD1940(false);
- }
-
- R2_GLOBALS._uiElements._active = true;
- R2_GLOBALS._uiElements._visible = true;
- SceneExt::remove();
-}
-
-void Scene1337::process(Event &event) {
- if (event.eventType == EVENT_BUTTON_DOWN) {
- if (event.btnState == BTNSHIFT_RIGHT) {
- updateCursorId(R2_GLOBALS._mouseCursorId, true);
- event.handled = true;
- } else if (_delayedFunction) {
- FunctionPtrType tmpFctPtr = _delayedFunction;
- _delayedFunction = nullptr;
- (this->*tmpFctPtr)();
- event.handled = true;
- }
- } else if (event.eventType == EVENT_KEYPRESS) {
- if (event.kbd.keycode == Common::KEYCODE_SPACE) {
- if (_delayedFunction) {
- FunctionPtrType tmpFctPtr = _delayedFunction;
- _delayedFunction = nullptr;
- (this->*tmpFctPtr)();
- event.handled = true;
- }
- } else
- warning("Fixme: Find proper keycode value");
- }
-
- if (!event.handled)
- Scene::process(event);
-}
-
-void Scene1337::dispatch() {
- if (!_instructionsDisplayedFl) {
- ++_instructionsWaitCount;
- if (_instructionsWaitCount == 4) {
- _instructionsDisplayedFl = true;
- suggestInstructions();
- }
- }
-
- // The following code is in the original in sceneHandler::process(),
- // which is terrible as it's checked in every scene of the game.
- setCursorData(5, _cursorCurStrip, _cursorCurFrame);
- //
-
- Scene::dispatch();
-}
-
-void Scene1337::actionDisplay(int resNum, int lineNum, int x, int y, int keepOnScreen, int width, int textMode, int fontNum, int colFG, int colBGExt, int colFGExt) {
- // TODO: Check if it's normal that arg5 is unused and replaced by an hardcoded 0 value
- // May hide an original bug
-
- SceneItem::display(resNum, lineNum, SET_X, x, SET_Y, y, SET_KEEP_ONSCREEN, 0,
- SET_WIDTH, width, SET_POS_MODE, -1, SET_TEXT_MODE, textMode,
- SET_FONT, fontNum, SET_FG_COLOR, colFG, SET_EXT_BGCOLOR, colBGExt,
- SET_EXT_FGCOLOR, colFGExt, LIST_END);
-}
-
-void Scene1337::setAnimationInfo(Card *card) {
- if (!card)
- return;
-
- if (card->_cardId > 25) {
- card->_card.setStrip2(4);
- card->_card.setFrame(card->_cardId - 25);
- } else if (card->_cardId > 9) {
- card->_card.setStrip2(3);
- card->_card.setFrame(card->_cardId - 9);
- } else {
- card->_card.setStrip2(2);
- card->_card.setFrame(card->_cardId);
- }
-
- card->_card.show();
- R2_GLOBALS._sceneObjects->draw();
-}
-
-void Scene1337::handleNextTurn() {
- switch (_winnerId) {
- case -1:
- ++_currentPlayerNumb;
- if (_currentPlayerNumb > 3)
- _currentPlayerNumb = 0;
-
- if (_showPlayerTurn) {
- _currentPlayerArrow.show();
- switch (_currentPlayerNumb) {
- case 0:
- _currentPlayerArrow.setStrip(3);
- break;
- case 1:
- _currentPlayerArrow.setStrip(4);
- break;
- case 2:
- subD1975(174, 107);
- _currentPlayerArrow.setStrip(1);
- break;
- case 3:
- subC4CEC();
- _currentPlayerArrow.setStrip(2);
- break;
- default:
- break;
- }
-
- if (!_autoplay)
- _delayedFunction = &Scene1337::handlePlayerTurn;
- else
- handlePlayerTurn();
- } else {
- handlePlayerTurn();
- }
- break;
- case 0:
- _aSound2.play(62);
- actionDisplay(1330, 135, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- actionDisplay(1330, 121, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- actionDisplay(1330, 122, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- R2_GLOBALS._sceneObjects->draw();
- actionDisplay(1330, 123, 159, 134, 1, 200, 0, 7, 0, 105, 105);
- break;
- case 1:
- _aSound2.play(62);
- actionDisplay(1330, 151, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- actionDisplay(1330, 118, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- actionDisplay(1330, 119, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- R2_GLOBALS._sceneObjects->draw();
- actionDisplay(1330, 120, 159, 134, 1, 200, 0, 7, 0, 105, 105);
- break;
- case 2:
- _aSound2.play(62);
- actionDisplay(1330, 134, 159, 134, 1, 200, 0, 7, 0, 105, 105);
- actionDisplay(1330, 124, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- actionDisplay(1330, 126, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- R2_GLOBALS._sceneObjects->draw();
- actionDisplay(1330, 125, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- break;
- case 3:
- _aSound2.play(62);
- actionDisplay(1330, 150, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- actionDisplay(1330, 115, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- actionDisplay(1330, 116, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- R2_GLOBALS._sceneObjects->draw();
- actionDisplay(1330, 117, 159, 134, 1, 200, 0, 7, 0, 105, 105);
- break;
- default:
- break;
- }
-
- if (_winnerId != -1)
- R2_GLOBALS._sceneManager.changeScene(125);
-
-}
-
-void Scene1337::handlePlayerTurn() {
- if (_showPlayerTurn)
- _currentPlayerArrow.hide();
-
- switch (_currentPlayerNumb) {
- case 2:
- subC4CD2();
- if (_displayHelpFl)
- actionDisplay(1330, 114, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- _displayHelpFl = false;
- // No break on purpose
- case 0:
- // No break on purpose
- case 1:
- // No break on purpose
- case 3:
- _actionItem.setAction(&_action4);
- default:
- break;
- }
-
- _showPlayerTurn = true;
-
-}
-
-bool Scene1337::isStationCard(int cardId) {
- switch (cardId) {
- case 10:
- // No break on purpose
- case 12:
- // No break on purpose
- case 15:
- // No break on purpose
- case 17:
- // No break on purpose
- case 18:
- // No break on purpose
- case 19:
- // No break on purpose
- case 20:
- // No break on purpose
- case 21:
- return true;
- default:
- return false;
- }
-}
-
-bool Scene1337::isStopConstructionCard(int cardId) {
- switch (cardId) {
- case 11:
- // No break on purpose
- case 14:
- // No break on purpose
- case 16:
- // No break on purpose
- case 24:
- return true;
- default:
- return false;
- }
-}
-
-int Scene1337::getStationId(int playerId, int handCardId) {
- if ((_gameBoardSide[playerId]._handCard[handCardId]._cardId > 1) && (_gameBoardSide[playerId]._handCard[handCardId]._cardId <= 9))
- return handCardId;
-
- return -1;
-}
-
-int Scene1337::findPlatformCardInHand(int playerId) {
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 1)
- return i;
- }
-
- return -1;
-}
-
-int Scene1337::findCard13InHand(int playerId) {
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 13)
- return i;
- }
-
- return -1;
-}
-
-int Scene1337::checkThieftCard(int playerId) {
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 25)
- return i;
- }
-
- return -1;
-}
-
-int Scene1337::isDelayCard(int cardId) {
- switch (cardId) {
- case 11:
- // No break on purpose
- case 14:
- // No break on purpose
- case 16:
- // No break on purpose
- case 24:
- return cardId;
- break;
- default:
- return -1;
- break;
- }
-}
-
-int Scene1337::getStationCardId(int cardId) {
- switch (cardId) {
- case 10:
- // No break on purpose
- case 12:
- // No break on purpose
- case 15:
- // No break on purpose
- case 17:
- // No break on purpose
- case 18:
- // No break on purpose
- case 19:
- // No break on purpose
- case 20:
- // No break on purpose
- case 21:
- return cardId;
- default:
- return -1;
- }
-}
-
-void Scene1337::handlePlayer01Discard(int playerId) {
- switch (playerId) {
- case 0:
- for (int i = 0; i <= 3; i++) {
- if (getStationCardId(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (isDelayCard(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if ((_gameBoardSide[playerId]._handCard[i]._cardId > 1) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 9)) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if ((_gameBoardSide[playerId]._handCard[i]._cardId >= 26) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 33)) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 1) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 25) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 13) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
- break;
- case 1:
- for (int i = 0; i <= 3; i++) {
- if ((_gameBoardSide[playerId]._handCard[i]._cardId >= 26) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 33)) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 1) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if ((_gameBoardSide[playerId]._handCard[i]._cardId > 1) && (_gameBoardSide[playerId]._handCard[i]._cardId <= 9)) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (getStationCardId(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (isDelayCard(_gameBoardSide[playerId]._handCard[i]._cardId) != -1) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 25) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (_gameBoardSide[playerId]._handCard[i]._cardId == 13) {
- discardCard(&_gameBoardSide[playerId]._handCard[i]);
- return;
- }
- }
-
- break;
- default:
- break;
- }
-}
-
-void Scene1337::playThieftCard(int playerId, Card *card, int victimId) {
- _actionIdx1 = playerId;
- _actionIdx2 = victimId;
-
- int randIndx;
-
- for (;;) {
- randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
- if (_gameBoardSide[victimId]._handCard[randIndx]._cardId != 0)
- break;
- }
-
- _actionCard1 = card;
- _actionCard2 = &_gameBoardSide[victimId]._emptyStationPos;
- _actionCard3 = &_gameBoardSide[victimId]._handCard[randIndx];
-
- _actionItem.setAction(&_action11);
-}
-
-int Scene1337::getPreventionCardId(int cardId) {
- int retVal;
-
- switch (cardId) {
- case 10:
- retVal = 2;
- break;
- case 12:
- retVal = 3;
- break;
- case 15:
- retVal = 5;
- break;
- case 17:
- retVal = 9;
- break;
- case 18:
- retVal = 6;
- break;
- case 19:
- retVal = 4;
- break;
- case 20:
- retVal = 8;
- break;
- case 21:
- retVal = 7;
- break;
- default:
- retVal = -1;
- }
-
- return retVal;
-}
-
-bool Scene1337::isAttackPossible(int victimId, int cardId) {
- if (victimId < 0 || victimId >= ARRAYSIZE(_gameBoardSide))
- error("Scene1337::isAttackPossible() victimId:%d out of range 0 to %d", victimId, ARRAYSIZE(_gameBoardSide)-1);
-
- for (int i = 0; i <= 7; i++) {
- if (_gameBoardSide[victimId]._outpostStation[i]._cardId != 0) {
- if (getPreventionCardId(cardId) == _gameBoardSide[victimId]._outpostStation[i]._cardId)
- return false;
- }
- }
- return true;
-}
-
-int Scene1337::getPlayerWithOutpost(int playerId) {
- int randPlayerId = R2_GLOBALS._randomSource.getRandomNumber(3);
-
- for (int i = 0; i <= 3; i++) {
- if (randPlayerId != playerId) {
- for (int j = 0; j <= 7; j++) {
- if (_gameBoardSide[randPlayerId]._outpostStation[j]._cardId != 0)
- return randPlayerId;
- }
- }
-
- if (playerId == 1) {
- randPlayerId--;
- if (randPlayerId < 0)
- randPlayerId = 3;
- } else {
- ++randPlayerId;
- if (randPlayerId > 3)
- randPlayerId = 0;
- }
- }
-
- return -1;
-}
-
-bool Scene1337::checkAntiDelayCard(int delayCardId, int cardId) {
- if ((delayCardId == 11) && (cardId == 26))
- return true;
-
- if ((delayCardId == 14) && (cardId == 30))
- return true;
-
- if ((delayCardId == 16) && (cardId == 32))
- return true;
-
- if ((delayCardId == 24) && (cardId == 28))
- return true;
-
- return false;
-}
-
-void Scene1337::playStationCard(Card *station, Card *platform) {
- _actionCard1 = station;
- _actionCard2 = platform;
- _actionItem.setAction(&_action7);
-}
-
-int Scene1337::getFreeHandCard(int playerId) {
- if ( (_gameBoardSide[playerId]._handCard[0]._cardId == 0)
- && (_gameBoardSide[playerId]._handCard[1]._cardId == 0)
- && (_gameBoardSide[playerId]._handCard[2]._cardId == 0)
- && (_gameBoardSide[playerId]._handCard[3]._cardId == 0))
- return -1;
-
- int randIndx;
- for (;;) {
- randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
- if (_gameBoardSide[playerId]._handCard[randIndx]._cardId == 0)
- break;
- }
-
- return randIndx;
-}
-
-void Scene1337::playPlatformCard(Card *card, Card *dest) {
- _actionCard1 = card;
- _actionCard2 = dest;
-
- _actionItem.setAction(&_action6);
-}
-
-void Scene1337::playDelayCard(Card *card, Card *dest) {
- _actionCard1 = card;
- _actionCard2 = dest;
-
- _actionItem.setAction(&_action9);
-}
-
-void Scene1337::playAntiDelayCard(Card *card, Card *dest) {
- _actionCard1 = card;
- _actionCard2 = dest;
-
- _actionItem.setAction(&_action8);
-
- handleNextTurn();
-}
-
-
-Scene1337::Card *Scene1337::getStationCard(int playerId) {
- for (int i = 0; i <= 7; i++) {
- if ((_gameBoardSide[playerId]._outpostStation[i]._cardId >= 1) && (_gameBoardSide[playerId]._outpostStation[i]._cardId <= 9))
- return &_gameBoardSide[playerId]._outpostStation[i];
- }
-
- return nullptr;
-}
-
-void Scene1337::playCounterTrickCard(Card *card, int playerId) {
- _actionCard1 = card;
- _actionCard2 = getStationCard(playerId);
- _actionCard3 = &_gameBoardSide[playerId]._emptyStationPos;
- _actionIdx1 = playerId;
- _actionItem.setAction(&_action10);
- handleNextTurn();
-}
-
-void Scene1337::discardCard(Card *card) {
- _actionCard1 = card;
-
- _actionItem.setAction(&_action5);
-}
-
-void Scene1337::subC4CD2() {
- if (R2_GLOBALS._v57709 > 0) {
- subD1917();
- subD1940(false); // _v5780C--
- }
-}
-
-void Scene1337::subC4CEC() {
- if (R2_GLOBALS._v57709 == 0) {
- subD18F5();
- subD1940(true); // _v5780C++
- }
-}
-
-void Scene1337::subC51A0(Card *subObj1, Card *subObj2) {
- _actionCard1 = subObj1;
- _actionCard2 = subObj2;
-
- _actionItem.setAction(&_action13);
-}
-
-void Scene1337::displayDialog(int dialogNumb) {
- switch (dialogNumb - 1) {
- case 0:
- actionDisplay(1330, 53, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 1:
- actionDisplay(1330, 57, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 2:
- actionDisplay(1330, 58, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 3:
- actionDisplay(1330, 59, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 4:
- actionDisplay(1330, 60, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 5:
- actionDisplay(1330, 61, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 6:
- actionDisplay(1330, 62, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 7:
- actionDisplay(1330, 63, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 8:
- actionDisplay(1330, 64, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 9:
- actionDisplay(1330, 65, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 10:
- actionDisplay(1330, 67, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 11:
- actionDisplay(1330, 69, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 12:
- actionDisplay(1330, 71, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- actionDisplay(1330, 72, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- actionDisplay(1330, 73, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 13:
- actionDisplay(1330, 79, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 14:
- actionDisplay(1330, 81, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- actionDisplay(1330, 83, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 16:
- actionDisplay(1330, 85, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 17:
- actionDisplay(1330, 87, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 18:
- actionDisplay(1330, 89, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 19:
- actionDisplay(1330, 91, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- actionDisplay(1330, 93, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 23:
- actionDisplay(1330, 95, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 24:
- actionDisplay(1330, 97, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 25:
- actionDisplay(1330, 104, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 26:
- actionDisplay(1330, 105, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- actionDisplay(1330, 106, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 27:
- actionDisplay(1330, 110, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 28:
- actionDisplay(1330, 108, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- actionDisplay(1330, 109, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 29:
- actionDisplay(1330, 111, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 31:
- actionDisplay(1330, 112, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
-}
-
-void Scene1337::subPostInit() {
- R2_GLOBALS._v57709 = 0;
- R2_GLOBALS._v5780C = 0;
- updateCursorId(1, false);
- subD1940(true); // _v5780C++
- subD18F5();
-
-// loadScene(1330);
-// SceneExt::postInit();
-
- R2_GLOBALS._scenePalette.addRotation(224, 235, 1);
-
- _availableCardsPile[0] = 1;
- _availableCardsPile[1] = 1;
- _availableCardsPile[2] = 1;
- _availableCardsPile[3] = 1;
- _availableCardsPile[4] = 1;
- _availableCardsPile[5] = 1;
- _availableCardsPile[6] = 1;
- _availableCardsPile[7] = 1;
- _availableCardsPile[8] = 26;
- _availableCardsPile[9] = 2;
- _availableCardsPile[10] = 2;
- _availableCardsPile[11] = 2;
- _availableCardsPile[12] = 2;
- _availableCardsPile[13] = 2;
- _availableCardsPile[14] = 26;
- _availableCardsPile[15] = 3;
- _availableCardsPile[16] = 3;
- _availableCardsPile[17] = 3;
- _availableCardsPile[18] = 3;
- _availableCardsPile[19] = 3;
- _availableCardsPile[20] = 28;
- _availableCardsPile[21] = 4;
- _availableCardsPile[22] = 4;
- _availableCardsPile[23] = 4;
- _availableCardsPile[24] = 4;
- _availableCardsPile[25] = 4;
- _availableCardsPile[26] = 28;
- _availableCardsPile[27] = 5;
- _availableCardsPile[28] = 5;
- _availableCardsPile[29] = 5;
- _availableCardsPile[30] = 5;
- _availableCardsPile[31] = 5;
- _availableCardsPile[32] = 30;
- _availableCardsPile[33] = 6;
- _availableCardsPile[34] = 6;
- _availableCardsPile[35] = 6;
- _availableCardsPile[36] = 6;
- _availableCardsPile[37] = 6;
- _availableCardsPile[38] = 30;
- _availableCardsPile[39] = 7;
- _availableCardsPile[40] = 7;
- _availableCardsPile[41] = 7;
- _availableCardsPile[42] = 7;
- _availableCardsPile[43] = 7;
- _availableCardsPile[44] = 32;
- _availableCardsPile[45] = 8;
- _availableCardsPile[46] = 8;
- _availableCardsPile[47] = 8;
- _availableCardsPile[48] = 8;
- _availableCardsPile[49] = 8;
- _availableCardsPile[50] = 32;
- _availableCardsPile[51] = 9;
- _availableCardsPile[52] = 9;
- _availableCardsPile[53] = 9;
- _availableCardsPile[54] = 9;
- _availableCardsPile[55] = 9;
- _availableCardsPile[56] = 10;
- _availableCardsPile[57] = 11;
- _availableCardsPile[58] = 12;
- _availableCardsPile[59] = 13;
- _availableCardsPile[60] = 13;
- _availableCardsPile[61] = 14;
- _availableCardsPile[62] = 15;
- _availableCardsPile[63] = 16;
- _availableCardsPile[64] = 17;
- _availableCardsPile[65] = 18;
- _availableCardsPile[66] = 19;
- _availableCardsPile[67] = 20;
- _availableCardsPile[68] = 21;
- _availableCardsPile[69] = 26;
- _availableCardsPile[70] = 28;
- _availableCardsPile[71] = 24;
- _availableCardsPile[72] = 25;
- _availableCardsPile[73] = 25;
- _availableCardsPile[74] = 25;
- _availableCardsPile[75] = 25;
- _availableCardsPile[76] = 26;
- _availableCardsPile[77] = 26;
- _availableCardsPile[78] = 26;
- _availableCardsPile[79] = 27;
- _availableCardsPile[80] = 27;
- _availableCardsPile[81] = 28;
- _availableCardsPile[82] = 28;
- _availableCardsPile[83] = 28;
- _availableCardsPile[84] = 29;
- _availableCardsPile[85] = 29;
- _availableCardsPile[86] = 29;
- _availableCardsPile[87] = 30;
- _availableCardsPile[88] = 30;
- _availableCardsPile[89] = 30;
- _availableCardsPile[90] = 30;
- _availableCardsPile[91] = 32;
- _availableCardsPile[92] = 1;
- _availableCardsPile[93] = 32;
- _availableCardsPile[94] = 32;
- _availableCardsPile[95] = 32;
- _availableCardsPile[96] = 1;
- _availableCardsPile[97] = 1;
- _availableCardsPile[98] = 1;
- _availableCardsPile[99] = 0;
-
- _cardsAvailableNumb = 98;
- _currentDiscardIndex = 98; // CHECKME: Would make more sense at pos 99
-
- _discardPile._cardId = 0;
- _discardPile._stationPos = Common::Point(128, 95);
-
- _stockCard._cardId = 0;
- _stockCard._stationPos = Common::Point(162, 95);
-
- _selectedCard._cardId = 0;
-
- _animatedCard._card.postInit();
- _animatedCard._card.setVisage(1332);
- _animatedCard._card.setStrip(5);
- _animatedCard._card.setFrame(1);
- _animatedCard._card._moveDiff = Common::Point(10, 10);
- _animatedCard._card.fixPriority(400);
- _animatedCard._card.setPosition(Common::Point(128, 95), 0);
- _animatedCard._card.animate(ANIM_MODE_2, NULL);
- _animatedCard._card.hide();
-
- _currentPlayerArrow.postInit();
- _currentPlayerArrow.setVisage(1334);
- _currentPlayerArrow.setStrip(1);
- _currentPlayerArrow.setFrame(1);
- _currentPlayerArrow._numFrames = 12;
- _currentPlayerArrow.fixPriority(500);
- _currentPlayerArrow.setPosition(Common::Point(174, 107), 0);
- _currentPlayerArrow.animate(ANIM_MODE_2, NULL);
- _currentPlayerArrow.hide();
-
- _showPlayerTurn = true;
- _displayHelpFl = false;
- _winnerId = -1;
-
- _helpIcon.postInit();
- _helpIcon.setup(9531, 1, 1);
- _helpIcon.setPosition(Common::Point(249, 168));
- _helpIcon.setPriority(155);
- _helpIcon._effect = EFFECT_NONE;
- _helpIcon.show();
-
- _autoplay = false;
- _instructionsDisplayedFl = false;
- _instructionsWaitCount = 0;
-}
-
-void Scene1337::suggestInstructions() {
- if (R2_GLOBALS._v57709 > 0)
- subD1917();
-
- if (MessageDialog::show(NEED_INSTRUCTIONS, NO_MSG, YES_MSG) == 0) {
- if (R2_GLOBALS._v57709 == 0)
- subD18F5();
- dealCards();
- } else {
- if (R2_GLOBALS._v57709 == 0)
- subD18F5();
- displayInstructions();
- }
-}
-
-void Scene1337::displayInstructions() {
- _actionItem.setAction(&_action1);
-}
-
-void Scene1337::shuffleCards() {
- R2_GLOBALS._sceneObjects->draw();
-
- // Remove holes in card pile
- for (int i = 0; i <= 98; i++) {
- if (_availableCardsPile[i] == 0) {
- for (int j = i + 1; j <= 98; j ++) {
- if (_availableCardsPile[j] != 0) {
- _availableCardsPile[i] = _availableCardsPile[j];
- _availableCardsPile[j] = 0;
- break;
- }
- }
- }
- }
-
- // Compute the number of available cards
- for (int i = 0; i <= 99; i ++) {
- if (_availableCardsPile[i] == 0) {
- // CHECKME: This will fail if i == 0, which shouldn't happen
- // as we don't shuffle cards when no card is available.
- _cardsAvailableNumb = i - 1;
- _currentDiscardIndex = 98; // CHECKME: Would make more sense at pos 99
- break;
- }
- }
-
- for (int i = 0; i < 2000; i ++) {
- int randIndx = R2_GLOBALS._randomSource.getRandomNumber(_cardsAvailableNumb);
- int swap = _availableCardsPile[0];
- _availableCardsPile[0] = _availableCardsPile[randIndx];
- _availableCardsPile[randIndx] = swap;
- }
-
- _shuffleEndedFl = false;
-
- // Shuffle cards
- _animatedCard._card.setAction(&_action2);
-
- while(!_shuffleEndedFl && !g_vm->shouldQuit()) {
- g_globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
- g_globals->_scenePalette.signalListeners();
- R2_GLOBALS._sceneObjects->draw();
- g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
- }
-}
-
-void Scene1337::dealCards() {
- _animatedCard._card._moveDiff = Common::Point(30, 30);
- shuffleCards();
-
- // Deal cards
- _actionItem.setAction(&_action3);
-}
-
-void Scene1337::showOptionsDialog() {
- // Display menu with "Auto Play", "New Game", "Quit" and "Continue"
- OptionsDialog::show();
-}
-
-void Scene1337::handleClick(int arg1, Common::Point pt) {
- 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)
- || _gameBoardSide[0]._outpostStation[i].isIn(pt)
- || _gameBoardSide[1]._outpostStation[i].isIn(pt)
- || _gameBoardSide[3]._outpostStation[i].isIn(pt) ) {
- found = true;
- break;
- }
- }
-
- if (found) {
- switch (curReg) {
- case 5:
- if (_gameBoardSide[2]._outpostStation[i]._cardId != 0)
- displayDialog(_gameBoardSide[2]._outpostStation[i]._cardId);
- else
- actionDisplay(1330, 20, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 10:
- if (_gameBoardSide[3]._outpostStation[i]._cardId != 0)
- displayDialog(_gameBoardSide[3]._outpostStation[i]._cardId);
- else
- actionDisplay(1330, 22, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- if (_gameBoardSide[0]._outpostStation[i]._cardId != 0)
- displayDialog(_gameBoardSide[0]._outpostStation[i]._cardId);
- else
- actionDisplay(1330, 21, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- if (_gameBoardSide[1]._outpostStation[i]._cardId != 0)
- displayDialog(_gameBoardSide[1]._outpostStation[i]._cardId);
- else
- actionDisplay(1330, 23, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- } else if ( _gameBoardSide[2]._delayCard.isIn(pt)
- || _gameBoardSide[0]._delayCard.isIn(pt)
- || _gameBoardSide[1]._delayCard.isIn(pt)
- || _gameBoardSide[3]._delayCard.isIn(pt) ) {
- switch (curReg) {
- case 5:
- if (_gameBoardSide[2]._delayCard._cardId != 0)
- displayDialog(_gameBoardSide[2]._delayCard._cardId);
- else
- actionDisplay(1330, 10, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 10:
- if (_gameBoardSide[3]._delayCard._cardId != 0)
- displayDialog(_gameBoardSide[3]._delayCard._cardId);
- else
- actionDisplay(1330, 16, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- if (_gameBoardSide[0]._delayCard._cardId != 0)
- displayDialog(_gameBoardSide[0]._delayCard._cardId);
- else
- actionDisplay(1330, 13, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- if (_gameBoardSide[1]._delayCard._cardId != 0)
- displayDialog(_gameBoardSide[1]._delayCard._cardId);
- else
- actionDisplay(1330, 18, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- } else if (_discardPile.isIn(pt)) {
- if (_discardPile._cardId != 0)
- displayDialog(_discardPile._cardId);
- else
- actionDisplay(1330, 7, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (_helpIcon._bounds.contains(pt))
- actionDisplay(1330, 43, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else if (_stockCard.isIn(pt))
- actionDisplay(1330, 4, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else if ( (_gameBoardSide[2]._emptyStationPos.isIn(pt))
- || (_gameBoardSide[3]._emptyStationPos.isIn(pt))
- || (_gameBoardSide[0]._emptyStationPos.isIn(pt))
- || (_gameBoardSide[1]._emptyStationPos.isIn(pt)) )
- actionDisplay(1330, 32, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else if (_gameBoardSide[2]._handCard[0].isIn(pt))
- displayDialog(_gameBoardSide[2]._handCard[0]._cardId);
- else if (_gameBoardSide[2]._handCard[1].isIn(pt))
- displayDialog(_gameBoardSide[2]._handCard[1]._cardId);
- else if (_gameBoardSide[2]._handCard[2].isIn(pt))
- displayDialog(_gameBoardSide[2]._handCard[2]._cardId);
- else if (_gameBoardSide[2]._handCard[3].isIn(pt))
- displayDialog(_gameBoardSide[2]._handCard[3]._cardId);
- else if ((curReg >= 6) && (curReg <= 9))
- actionDisplay(1330, 29, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else if ((curReg >= 11) && (curReg <= 14))
- actionDisplay(1330, 31, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else if ((curReg >= 16) && (curReg <= 19))
- actionDisplay(1330, 30, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else {
- switch (curReg) {
- case 0:
- actionDisplay(1330, 2, 159, 134, 1, 200, 0, 7, 0, 105, 105);
- break;
- case 5:
- actionDisplay(1330, 25, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 10:
- actionDisplay(1330, 27, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- actionDisplay(1330, 26, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- actionDisplay(1330, 28, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 21:
- actionDisplay(1330, 24, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- }
- }
-
- if (arg1 != 1)
- return;
-
- for (int i = 0; i <= 7; i++) {
- if (_gameBoardSide[2]._outpostStation[i].isIn(pt)) {
- switch (_gameBoardSide[2]._outpostStation[i]._cardId) {
- case 0:
- actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 1:
- actionDisplay(1330, 54, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- actionDisplay(1330, 34, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- }
- return;
- }
- if (_gameBoardSide[0]._outpostStation[i].isIn(pt)) {
- switch (_gameBoardSide[0]._outpostStation[i]._cardId) {
- case 0:
- actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- }
- return;
- }
- if (_gameBoardSide[1]._outpostStation[i].isIn(pt)) {
- switch (_gameBoardSide[1]._outpostStation[i]._cardId) {
- case 0:
- actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- break;
- default:
- actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- break;
- }
- return;
- }
- if (_gameBoardSide[3]._outpostStation[i].isIn(pt)) {
- switch (_gameBoardSide[3]._outpostStation[i]._cardId) {
- case 0:
- actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- break;
- default:
- actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- break;
- }
- return;
- }
- }
-
- if (_gameBoardSide[2]._delayCard.isIn(pt)) {
- // The original uses _gameBoardSide[0], which is obviously a bug.
- if (_gameBoardSide[2]._delayCard._cardId != 0)
- actionDisplay(1330, 39, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else
- actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- return;
- }
- if (_gameBoardSide[3]._delayCard.isIn(pt)) {
- if (_gameBoardSide[3]._delayCard._cardId != 0)
- actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- else
- actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
-
- return;
- }
- if (_gameBoardSide[1]._delayCard.isIn(pt)) {
- if (_gameBoardSide[1]._delayCard._cardId != 0)
- actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- else
- actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
-
- return;
- }
- if (_gameBoardSide[0]._delayCard.isIn(pt)) {
- if (_gameBoardSide[0]._delayCard._cardId != 0)
- actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else
- actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
-
- return;
- }
- if (_gameBoardSide[3]._emptyStationPos.isIn(pt)) {
- actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- return;
- }
- if (_gameBoardSide[1]._emptyStationPos.isIn(pt)) {
- actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- return;
- }
- if (_gameBoardSide[0]._emptyStationPos.isIn(pt)) {
- actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- return;
- }
-
- if (_helpIcon._bounds.contains(pt)) {
- showOptionsDialog();
- return;
- }
-
- if (_discardPile.isIn(pt))
- actionDisplay(1330, 9, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else if (_stockCard.isIn(pt))
- actionDisplay(1330, 5, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- else {
- switch (curReg) {
- case 0:
- actionDisplay(1330, 3, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 6:
- // no break on purpose
- case 7:
- // no break on purpose
- case 8:
- // no break on purpose
- case 9:
- actionDisplay(1330, 145, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- break;
- case 10:
- actionDisplay(1330, 147, 20, 99, 1, 136, 0, 7, 0, 172, 172);
- break;
- case 11:
- // no break on purpose
- case 12:
- // no break on purpose
- case 13:
- // no break on purpose
- case 14:
- actionDisplay(1330, 1, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 16:
- // no break on purpose
- case 17:
- // no break on purpose
- case 18:
- // no break on purpose
- case 19:
- actionDisplay(1330, 144, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- break;
- case 20:
- actionDisplay(1330, 146, 300, 99, 1, 136, 0, 7, 0, 117, 117);
- break;
- default:
- actionDisplay(1330, 11, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- }
- }
-}
-
-void Scene1337::handlePlayer0() {
- if (_gameBoardSide[0]._delayCard._cardId != 0) {
- switch (_gameBoardSide[0]._delayCard._cardId) {
- case 10:
- //No break on purpose
- case 12:
- //No break on purpose
- case 15:
- //No break on purpose
- case 17:
- //No break on purpose
- case 18:
- //No break on purpose
- case 19:
- //No break on purpose
- case 20:
- //No break on purpose
- case 21:
- discardCard(&_gameBoardSide[0]._delayCard);
- break;
- default:
- for (int i = 0; i <= 3; i++) {
- if (checkAntiDelayCard(_gameBoardSide[0]._delayCard._cardId, _gameBoardSide[0]._handCard[i]._cardId)) {
- playAntiDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[0]._delayCard);
- return;
- }
- }
-
- break;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- int tmpVal = getStationId(0, i);
-
- if (tmpVal != -1) {
- bool stationAlreadyPresentFl = false;
- for (int j = 0; j <= 7; j++) {
- if (_gameBoardSide[0]._outpostStation[j]._cardId == _gameBoardSide[0]._handCard[tmpVal]._cardId) {
- stationAlreadyPresentFl = true;
- break;
- }
- }
-
- if (!stationAlreadyPresentFl) {
- for (int j = 0; j <= 7; j++) {
- if ((_gameBoardSide[0]._outpostStation[j]._cardId == 1) && !isStopConstructionCard(_gameBoardSide[0]._delayCard._cardId)) {
- int stationCount = 0;
- for (int k = 0; k <= 7; k++) {
- if ((_gameBoardSide[0]._outpostStation[k]._cardId > 1) && (_gameBoardSide[0]._outpostStation[k]._cardId <= 9)) {
- ++stationCount;
- }
- }
-
- if (stationCount == 7)
- _winnerId = 0;
-
- playStationCard(&_gameBoardSide[0]._handCard[tmpVal], &_gameBoardSide[0]._outpostStation[j]);
- return;
- }
- }
- }
- }
- }
-
- int tmpVal = findPlatformCardInHand(0);
-
- if (tmpVal != -1) {
- for (int i = 0; i <= 7; i++) {
- if ((_gameBoardSide[0]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[0]._delayCard._cardId)) {
- playPlatformCard(&_gameBoardSide[0]._handCard[tmpVal], &_gameBoardSide[0]._outpostStation[i]);
- return;
- }
- }
- }
-
- int card13Id = findCard13InHand(0);
- if (card13Id != -1) {
- for (int i = 0; i <= 7; i++) {
- if (_gameBoardSide[2]._outpostStation[i]._cardId != 0) {
- playCounterTrickCard(&_gameBoardSide[0]._handCard[card13Id], 2);
- return;
- }
- }
- }
-
- int thieftId = checkThieftCard(0);
- if (thieftId != -1) {
- if ( (_gameBoardSide[2]._handCard[0]._cardId != 0)
- || (_gameBoardSide[2]._handCard[1]._cardId != 0)
- || (_gameBoardSide[2]._handCard[2]._cardId != 0)
- || (_gameBoardSide[2]._handCard[3]._cardId != 0) ) {
- playThieftCard(0, &_gameBoardSide[0]._handCard[thieftId], 2);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if ((isDelayCard(_gameBoardSide[0]._handCard[i]._cardId) != -1)
- && (_gameBoardSide[2]._delayCard._cardId == 0)
- && isAttackPossible(2, _gameBoardSide[0]._handCard[i]._cardId)) {
- playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[2]._delayCard);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if ((getStationCardId(_gameBoardSide[0]._handCard[i]._cardId) != -1)
- && (_gameBoardSide[2]._delayCard._cardId == 0)
- && isAttackPossible(2, _gameBoardSide[0]._handCard[i]._cardId)) {
- playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[2]._delayCard);
- return;
- }
- }
-
- card13Id = findCard13InHand(0);
- int victimPlayerId = getPlayerWithOutpost(0);
-
- if ((card13Id != -1) && (victimPlayerId != -1)) {
- playCounterTrickCard(&_gameBoardSide[0]._handCard[card13Id], victimPlayerId);
- return;
- }
-
- thieftId = checkThieftCard(0);
- if (thieftId != -1) {
- if ( (_gameBoardSide[1]._handCard[0]._cardId != 0)
- || (_gameBoardSide[1]._handCard[1]._cardId != 0)
- || (_gameBoardSide[1]._handCard[2]._cardId != 0)
- || (_gameBoardSide[1]._handCard[3]._cardId != 0) ) {
- playThieftCard(0, &_gameBoardSide[0]._handCard[thieftId], 1);
- return;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- if (getStationCardId(_gameBoardSide[0]._handCard[i]._cardId) != -1) {
- if ((_gameBoardSide[1]._delayCard._cardId == 0) && isAttackPossible(1, _gameBoardSide[0]._handCard[i]._cardId)) {
- playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[1]._delayCard);
- return;
- }
-
- if ((_gameBoardSide[3]._delayCard._cardId == 0) && isAttackPossible(3, _gameBoardSide[0]._handCard[i]._cardId)) {
- playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[3]._delayCard);
- return;
- }
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- tmpVal = isDelayCard(_gameBoardSide[0]._handCard[i]._cardId);
- if (tmpVal != -1) {
- if ((_gameBoardSide[1]._delayCard._cardId == 0) && isAttackPossible(1, _gameBoardSide[0]._handCard[i]._cardId)) {
- playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[1]._delayCard);
- return;
- }
-
- if ((_gameBoardSide[3]._delayCard._cardId == 0) && isAttackPossible(3, _gameBoardSide[0]._handCard[i]._cardId)) {
- playDelayCard(&_gameBoardSide[0]._handCard[i], &_gameBoardSide[3]._delayCard);
- return;
- }
- }
- }
-
- handlePlayer01Discard(0);
-}
-
-void Scene1337::handlePlayer1() {
- if (this->_gameBoardSide[1]._delayCard._cardId != 0) {
- switch (_gameBoardSide[1]._delayCard._cardId) {
- case 10:
- // No break on purpose
- case 12:
- // No break on purpose
- case 15:
- // No break on purpose
- case 17:
- // No break on purpose
- case 18:
- // No break on purpose
- case 19:
- // No break on purpose
- case 20:
- // No break on purpose
- case 21:
- discardCard(&_gameBoardSide[1]._delayCard);
- return;
- default:
- for (int i = 0; i <= 3; i++) {
- if (checkAntiDelayCard(_gameBoardSide[1]._delayCard._cardId, _gameBoardSide[1]._handCard[i]._cardId)) {
- playAntiDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[1]._delayCard);
- return;
- }
- }
- break;
- }
- }
-
- for (int i = 0; i <= 3; i++) {
- int tmpIndx = getStationId(1, i);
- if (tmpIndx == -1)
- break;
-
- int tmpVal = 0;
- for (int j = 0; j <= 7; j++) {
- if (_gameBoardSide[1]._outpostStation[j]._cardId == _gameBoardSide[1]._handCard[tmpIndx]._cardId) {
- tmpVal = 1;
- break;
- }
- }
-
- if (tmpVal == 0)
- break;
-
- for (int j = 0; j <= 7; j++) {
- if ((_gameBoardSide[1]._outpostStation[j]._cardId == 1) && !isStopConstructionCard(_gameBoardSide[1]._delayCard._cardId)) {
- int stationCount = 0;
- for (int k = 0; k <= 7; k++) {
- if ((_gameBoardSide[1]._outpostStation[k]._cardId > 1) && (_gameBoardSide[1]._outpostStation[k]._cardId <= 9))
- ++stationCount;
- }
-
- if (stationCount == 7)
- _winnerId = 1;
-
- playStationCard(&_gameBoardSide[1]._handCard[tmpIndx], &_gameBoardSide[1]._outpostStation[j]);
- return;
- }
- }
- }
-
- int normalCardId = findPlatformCardInHand(1);
- if (normalCardId != -1) {
- for (int i = 0; i <= 7; i++) {
- if ((_gameBoardSide[1]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[1]._delayCard._cardId)) {
- playPlatformCard(&_gameBoardSide[1]._handCard[normalCardId], &_gameBoardSide[1]._outpostStation[i]);
- return;
- }
- }
- }
-
- int card13Id = findCard13InHand(1);
- int tmpVal2 = getPlayerWithOutpost(1);
-
- if ((card13Id != -1) && (tmpVal2 != -1)) {
- playCounterTrickCard(&_gameBoardSide[1]._handCard[card13Id], tmpVal2);
- return;
- }
-
- int thieftId = checkThieftCard(1);
- if (thieftId != -1) {
- int playerIdFound = -1;
- int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
- for (int i = 0; i <= 3; i++) {
- if (rndVal != 1) {
- if ( (_gameBoardSide[rndVal]._handCard[0]._cardId != 0)
- || (_gameBoardSide[rndVal]._handCard[1]._cardId != 0)
- || (_gameBoardSide[rndVal]._handCard[2]._cardId != 0)
- || (_gameBoardSide[rndVal]._handCard[3]._cardId == 0)) {
- playerIdFound = rndVal;
- break;
- }
- }
- // The original was only updating in the rndVal block,
- // which was a bug as the checks were stopping at this point
- rndVal--;
- if (rndVal < 0)
- rndVal = 3;
- }
-
- if (playerIdFound != -1) {
- playThieftCard(1, &_gameBoardSide[1]._handCard[thieftId], playerIdFound);
- return;
- }
- }
-
- int count = -1;
- int i;
- for (i = 0; i <= 3; i++) {
- int tmpVal = isDelayCard(_gameBoardSide[1]._handCard[i]._cardId);
- if (tmpVal != -1) {
- int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
-
- for (int j = 0; j <= 3; j++) {
- //CHECKME: tmpVal or rndVal?
- // FIXME: This is probably meant to be rndVal, but not clear...
- if (tmpVal < 0 || tmpVal >= ARRAYSIZE(_gameBoardSide))
- error("Scene1337::handlePlayer1() tmpVal:%d out of range 0 to %d", tmpVal, ARRAYSIZE(_gameBoardSide)-1);
-
- if (tmpVal != 1) {
- if ((_gameBoardSide[tmpVal]._delayCard._cardId == 0) && isAttackPossible(tmpVal, _gameBoardSide[1]._handCard[i]._cardId))
- count = tmpVal;
- }
-
- if (count < 0 || count >= ARRAYSIZE(_gameBoardSide))
- error("Scene1337::handlePlayer1() count:%d out of range 0 to %d", count, ARRAYSIZE(_gameBoardSide)-1);
-
- if (count != -1) {
- playDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[count]._delayCard);
- return;
- } else {
- rndVal--;
- if (rndVal < 0)
- rndVal = 3;
- }
- }
- }
- }
-
- int j;
- for (j = 0; j <= 3; j++) {
- if (getStationCardId(_gameBoardSide[1]._handCard[j]._cardId) != -1) {
- count = -1;
- int rndVal = R2_GLOBALS._randomSource.getRandomNumber(3);
- for (int l = 0; l <= 3; l++) {
- if (rndVal != 1) {
- if ((_gameBoardSide[rndVal]._delayCard._cardId == 0) && (_gameBoardSide[1]._handCard[j]._cardId == 1))
- count = rndVal;
- }
- if (count != -1) {
- playDelayCard(&_gameBoardSide[1]._handCard[j], &_gameBoardSide[count]._delayCard);
- return;
- } else {
- rndVal--;
- if (rndVal < 0)
- rndVal = 3;
- }
- }
- }
- }
-
- handlePlayer01Discard(1);
-}
-
-void Scene1337::handlePlayer3() {
- if (_gameBoardSide[3]._delayCard._cardId != 0) {
- switch (_gameBoardSide[3]._delayCard._cardId) {
- case 10:
- // No break on purpose
- case 12:
- // No break on purpose
- case 15:
- // No break on purpose
- case 17:
- // No break on purpose
- case 18:
- // No break on purpose
- case 19:
- // No break on purpose
- case 20:
- // No break on purpose
- case 21:
- discardCard(&_gameBoardSide[3]._delayCard);
- return;
- default:
- for (int i = 0; i <= 3; i++) {
- if (checkAntiDelayCard(_gameBoardSide[3]._delayCard._cardId, _gameBoardSide[3]._handCard[i]._cardId)) {
- playAntiDelayCard(&_gameBoardSide[3]._handCard[i], &_gameBoardSide[3]._delayCard);
- return;
- }
- }
- break;
- }
- }
-
- int randIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
-
- if (_gameBoardSide[3]._handCard[randIndx]._cardId == 1) {
- for (int i = 0; i <= 7; i++) {
- if ((_gameBoardSide[3]._outpostStation[i]._cardId == 0) && !isStopConstructionCard(_gameBoardSide[3]._delayCard._cardId)) {
- playPlatformCard(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[3]._outpostStation[i]);
- return;
- }
- }
- } else if (_gameBoardSide[3]._handCard[randIndx]._cardId <= 9) {
- for (int i = 0; i <= 7; i++) {
- if (_gameBoardSide[3]._outpostStation[i]._cardId == _gameBoardSide[3]._handCard[randIndx]._cardId) {
- discardCard(&_gameBoardSide[3]._handCard[randIndx]);
- return;
- }
- }
-
- for (int i = 0; i <= 7; i++) {
- if ((_gameBoardSide[3]._outpostStation[i]._cardId == 1) && !isStopConstructionCard(_gameBoardSide[3]._delayCard._cardId)) {
- int stationCount = 0;
- for (int j = 0; j <= 7; j++) {
- if ((_gameBoardSide[3]._outpostStation[j]._cardId > 1) && (_gameBoardSide[3]._outpostStation[j]._cardId <= 9))
- ++stationCount;
- }
-
- if (stationCount == 7)
- _winnerId = 3;
-
- playStationCard(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[3]._outpostStation[i]);
- return;
- }
- }
- } else if (_gameBoardSide[3]._handCard[randIndx]._cardId == 13) {
- int victimId = getPlayerWithOutpost(3);
-
- if (victimId != -1) {
- playCounterTrickCard(&_gameBoardSide[3]._handCard[randIndx], victimId);
- return;
- }
- } else if (_gameBoardSide[3]._handCard[randIndx]._cardId == 25) {
- int victimId = -1;
- int tmpRandIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
-
- for (int i = 0; i <= 3; i++) {
- if ( (tmpRandIndx != 3)
- && ( (_gameBoardSide[tmpRandIndx]._handCard[0]._cardId != 0)
- || (_gameBoardSide[tmpRandIndx]._handCard[1]._cardId != 0)
- || (_gameBoardSide[tmpRandIndx]._handCard[2]._cardId != 0)
- || (_gameBoardSide[tmpRandIndx]._handCard[3]._cardId != 0) )) {
- victimId = tmpRandIndx;
- break;
- }
-
- ++tmpRandIndx;
- if (tmpRandIndx > 3)
- tmpRandIndx = 0;
- }
-
- if (victimId != -1) {
- playThieftCard(3, &_gameBoardSide[3]._handCard[randIndx], victimId);
- return;
- }
- } else {
- switch (_gameBoardSide[3]._handCard[randIndx]._cardId) {
- case 10:
- // No break on purpose
- case 11:
- // No break on purpose
- case 12:
- // No break on purpose
- case 14:
- // No break on purpose
- case 15:
- // No break on purpose
- case 16:
- // No break on purpose
- case 17:
- // No break on purpose
- case 18:
- // No break on purpose
- case 19:
- // No break on purpose
- case 20:
- // No break on purpose
- case 21:
- // No break on purpose
- case 24: {
- int victimId = -1;
- int tmpRandIndx = R2_GLOBALS._randomSource.getRandomNumber(3);
-
- for (int i = 0; i <= 3; i++) {
- if (tmpRandIndx != 3) {
- if ((_gameBoardSide[tmpRandIndx]._delayCard._cardId == 0)
- && isAttackPossible(tmpRandIndx, _gameBoardSide[3]._handCard[randIndx]._cardId))
- victimId = tmpRandIndx;
- }
-
- ++tmpRandIndx;
- if (tmpRandIndx > 3)
- tmpRandIndx = 0;
-
- if (victimId != -1)
- break;
- }
-
- if (victimId != -1) {
- // Useless second identical check skipped
- playDelayCard(&_gameBoardSide[3]._handCard[randIndx], &_gameBoardSide[victimId]._delayCard);
- return;
- }
- }
- default:
- break;
- }
- }
-
- discardCard(&_gameBoardSide[3]._handCard[randIndx]);
-}
-
-void Scene1337::handleAutoplayPlayer2() {
- if (getStationCardId(this->_gameBoardSide[2]._delayCard._cardId) == -1)
- _delayedFunction = &Scene1337::handlePlayer2;
- else
- discardCard(&_gameBoardSide[2]._delayCard);
-}
-
-void Scene1337::handlePlayer2() {
- _selectedCard._stationPos = g_globals->_events._mousePos;
-
- if (R2_GLOBALS._v57810 == 200) {
- // Hand
- int i;
- for (i = 0; i < 4; i++) {
- if ((_gameBoardSide[2]._handCard[i].isIn(_selectedCard._stationPos)) && (_gameBoardSide[2]._handCard[i]._cardId != 0)) {
- Card *handcard = &_gameBoardSide[2]._handCard[i];
- _selectedCard._cardId = handcard->_cardId;
- _selectedCard._stationPos = handcard->_stationPos;
- //warning("_selectedCard._actorName = handcard->_actorName;");
- //warning("_selectedCard._fieldE = handcard->_fieldE;");
- //warning("_selectedCard._field10 = handcard->_field10;");
- //warning("_selectedCard._field12 = handcard->_field12;");
- //warning("_selectedCard._field14 = handcard->_field14;");
- //warning("_selectedCard._field16 = handcard->_field16;");
- _selectedCard._sceneRegionId = handcard->_sceneRegionId;
- _selectedCard._position = handcard->_position;
- _selectedCard._yDiff = handcard->_yDiff;
- _selectedCard._bounds = handcard->_bounds;
- _selectedCard._resNum = handcard->_resNum;
- _selectedCard._lookLineNum = handcard->_lookLineNum;
- _selectedCard._talkLineNum = handcard->_talkLineNum;
- _selectedCard._useLineNum = handcard->_useLineNum;
- _selectedCard._action = handcard->_action;
- //warning("_selectedCard._field0 = handcard->_field0;");
- _selectedCard._card._updateStartFrame = handcard->_card._updateStartFrame;
- _selectedCard._card._walkStartFrame = handcard->_card._walkStartFrame;
- // _field2E is named _field3C in R2R
- _selectedCard._card._oldPosition = handcard->_card._oldPosition;
- _selectedCard._card._percent = handcard->_card._percent;
- _selectedCard._card._priority = handcard->_card._priority;
- _selectedCard._card._angle = handcard->_card._angle;
- _selectedCard._card._flags = handcard->_card._flags;
- _selectedCard._card._xe = handcard->_card._xe;
- _selectedCard._card._xs = handcard->_card._xs;
- _selectedCard._card._paneRects[0] = handcard->_card._paneRects[0];
- _selectedCard._card._paneRects[1] = handcard->_card._paneRects[1];
- _selectedCard._card._visage = handcard->_card._visage;
- _selectedCard._card._objectWrapper = handcard->_card._objectWrapper;
- _selectedCard._card._strip = handcard->_card._strip;
- _selectedCard._card._animateMode = handcard->_card._animateMode;
- _selectedCard._card._frame = handcard->_card._frame;
- _selectedCard._card._endFrame = handcard->_card._endFrame;
- // _field68 is named _field76 in R2R
- _selectedCard._card._loopCount = handcard->_card._loopCount;
- _selectedCard._card._frameChange = handcard->_card._frameChange;
- _selectedCard._card._numFrames = handcard->_card._numFrames;
- _selectedCard._card._regionIndex = handcard->_card._regionIndex;
- _selectedCard._card._mover = handcard->_card._mover;
- _selectedCard._card._moveDiff = handcard->_card._moveDiff;
- _selectedCard._card._moveRate = handcard->_card._moveRate;
- _selectedCard._card._actorDestPos = handcard->_card._actorDestPos;
- _selectedCard._card._endAction = handcard->_card._endAction;
- _selectedCard._card._regionBitList = handcard->_card._regionBitList;
- // _selectedCard._object1._actorName = handcard->_object1._actorName;
- //warning("_selectedCard._card._fieldE = handcard->_card._fieldE;");
- //warning("_selectedCard._card._field10 = handcard->_card._field10;");
- //warning("_selectedCard._card._field12 = handcard->_card._field12;");
- //warning("_selectedCard._card._field14 = handcard->_card._field14;");
- //warning("_selectedCard._card._field16 = handcard->_card._field16;");
-
- _gameBoardSide[2]._handCard[i]._cardId = 0;
- _gameBoardSide[2]._handCard[i]._card.remove();
- break;
- }
- }
-
- if (i == 4) {
- handleClick(1, _selectedCard._stationPos);
- handleAutoplayPlayer2();
- return;
- } else {
- setCursorData(1332, _selectedCard._card._strip, _selectedCard._card._frame);
- R2_GLOBALS._sceneObjects->draw();
- }
- } else if (R2_GLOBALS._v57810 == 300) {
- // Eye
- handleClick(3, _selectedCard._stationPos);
- handleAutoplayPlayer2();
- return;
- } else {
- // The original code is calling a function full of dead code.
- // Only this message remains after a cleanup.
- MessageDialog::show(WRONG_ANSWER_MSG, OK_BTN_STRING);
- //
- handleAutoplayPlayer2();
- return;
- }
-
- Event event;
- bool found;
- for (;;) {
- if ( ((g_globals->_events.getEvent(event, EVENT_BUTTON_DOWN)) && (event.btnState == BTNSHIFT_RIGHT))
- || (g_globals->_events.getEvent(event, EVENT_KEYPRESS)) ){
- _selectedCard._stationPos = g_globals->_events._mousePos;
- found = false;
-
- for (int i = 0; i <= 3; i ++) {
- if (_gameBoardSide[2]._handCard[i].isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if (_gameBoardSide[2]._handCard[i]._cardId == 0) {
- _gameBoardSide[2]._handCard[i]._cardId = _selectedCard._cardId;
- _gameBoardSide[2]._handCard[i]._card.postInit();
- _gameBoardSide[2]._handCard[i]._card.hide();
- _gameBoardSide[2]._handCard[i]._card.setVisage(1332);
- _gameBoardSide[2]._handCard[i]._card.setPosition(_gameBoardSide[2]._handCard[i]._stationPos, 0);
- _gameBoardSide[2]._handCard[i]._card.fixPriority(170);
- setAnimationInfo(&_gameBoardSide[2]._handCard[i]);
- setCursorData(5, 1, 4);
- _currentPlayerNumb--;
- _showPlayerTurn = false;
- handleNextTurn();
- return;
- } else {
- actionDisplay(1330, 127, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- found = true;
- }
- break;
- }
- }
-
- if (!found) {
- if (_discardPile.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- discardCard(&_selectedCard);
- return;
- } else if (_selectedCard._cardId == 1) {
- bool isInCardFl = false;
- int i;
- for (i = 0; i <= 7; i++) {
- if (_gameBoardSide[2]._outpostStation[i].isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- isInCardFl = true;
- break;
- }
- }
-
- if ((isInCardFl) && (_gameBoardSide[2]._outpostStation[i]._cardId == 0)) {
- if (isDelayCard(_gameBoardSide[2]._delayCard._cardId) != -1) {
- actionDisplay(1330, 55, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else {
- playPlatformCard(&_selectedCard, &_gameBoardSide[2]._outpostStation[i]);
- return;
- }
- } else {
- actionDisplay(1330, 56, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else if (_selectedCard._cardId <= 9) {
- bool isInCardFl = false;
- int i;
- for (i = 0; i <= 7; i++) {
- if (_gameBoardSide[2]._outpostStation[i].isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- isInCardFl = true;
- break;
- }
- }
- if ((isInCardFl) && (_gameBoardSide[2]._outpostStation[i]._cardId == 1)) {
- isInCardFl = false;
- for (int j = 0; j <= 7; j++) {
- if (_selectedCard._cardId == _gameBoardSide[2]._outpostStation[j]._cardId) {
- isInCardFl = true;
- break;
- }
- }
- if (isInCardFl) {
- // This station is already in place
- actionDisplay(1330, 34, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (isDelayCard(_gameBoardSide[2]._delayCard._cardId) != -1) {
- // You must eliminate your delay before you can play a station
- actionDisplay(1330, 35, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else {
- int stationCount = 0;
- for (int k = 0; k <= 7; k++) {
- if ((_gameBoardSide[2]._outpostStation[k]._cardId > 1) && (_gameBoardSide[2]._outpostStation[k]._cardId <= 9))
- ++stationCount;
- }
-
- if (stationCount == 7)
- _winnerId = 2;
-
- playStationCard(&_selectedCard, &_gameBoardSide[2]._outpostStation[i]);
- return;
- }
- } else {
- actionDisplay(1330, 37, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else if ((_selectedCard._cardId == 26) || (_selectedCard._cardId == 30) ||(_selectedCard._cardId == 32) || (_selectedCard._cardId == 28)) {
- // Check anti-delay card
- if (_gameBoardSide[2]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- actionDisplay(1330, 42, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (checkAntiDelayCard(_gameBoardSide[2]._delayCard._cardId, _selectedCard._cardId)) {
- playAntiDelayCard(&_selectedCard, &_gameBoardSide[2]._delayCard);
- return;
- } else {
- if (_gameBoardSide[2]._delayCard._cardId != 0) {
- switch (_gameBoardSide[2]._delayCard._cardId) {
- case 11:
- actionDisplay(1330, 68, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 14:
- actionDisplay(1330, 80, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 16:
- actionDisplay(1330, 84, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 24:
- actionDisplay(1330, 96, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- } else {
- actionDisplay(1330, 41, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- }
- } else if ((getStationCardId(_selectedCard._cardId) == -1) && (isDelayCard(_selectedCard._cardId) == -1)) {
- if (_selectedCard._cardId == 13) {
- if (_gameBoardSide[0]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- for (int k = 0; k <= 7; k++) {
- if (_gameBoardSide[0]._outpostStation[k]._cardId != 0) {
- playCounterTrickCard(&_selectedCard, 0);
- return;
- }
- }
- actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (_gameBoardSide[3]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- for (int k = 0; k <= 7; k++) {
- if (_gameBoardSide[3]._outpostStation[k]._cardId != 0) {
- playCounterTrickCard(&_selectedCard, 3);
- return;
- }
- }
- actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (_gameBoardSide[1]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- for (int k = 0; k <= 7; k++) {
- if (_gameBoardSide[1]._outpostStation[k]._cardId == 0) {
- playCounterTrickCard(&_selectedCard, 1);
- return;
- }
- }
- actionDisplay(1330, 74, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else {
- actionDisplay(1330, 128, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else if (_selectedCard._cardId == 25) {
- if (_gameBoardSide[0]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if ( (_gameBoardSide[0]._handCard[0]._cardId != 0)
- || (_gameBoardSide[0]._handCard[1]._cardId != 0)
- || (_gameBoardSide[0]._handCard[2]._cardId != 0)
- || (_gameBoardSide[0]._handCard[3]._cardId != 0) ) {
- int k;
- for (k = 0; k <= 3; k++){
- if (_gameBoardSide[2]._handCard[k]._cardId == 0)
- break;
- }
- playThieftCard(2, &_gameBoardSide[2]._handCard[k], 0);
- return;
- } else {
- actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else if (_gameBoardSide[1]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if ( (_gameBoardSide[1]._handCard[0]._cardId != 0)
- || (_gameBoardSide[1]._handCard[1]._cardId != 0)
- || (_gameBoardSide[1]._handCard[2]._cardId != 0)
- || (_gameBoardSide[1]._handCard[3]._cardId != 0) ) {
- int k;
- for (k = 0; k <= 3; k++){
- if (_gameBoardSide[2]._handCard[k]._cardId == 0)
- break;
- }
- playThieftCard(2, &_gameBoardSide[2]._handCard[k], 1);
- return;
- } else {
- actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- }
-
- if (_gameBoardSide[3]._emptyStationPos.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if ( (_gameBoardSide[3]._handCard[0]._cardId != 0)
- || (_gameBoardSide[3]._handCard[1]._cardId != 0)
- || (_gameBoardSide[3]._handCard[2]._cardId != 0)
- || (_gameBoardSide[3]._handCard[3]._cardId != 0) ) {
- int k;
- for (k = 0; k <= 3; k++){
- if (_gameBoardSide[2]._handCard[k]._cardId == 0)
- break;
- }
- playThieftCard(2, &_gameBoardSide[2]._handCard[k], 3);
- return;
- } else {
- actionDisplay(1330, 99, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else {
- actionDisplay(1330, 129, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else if (_selectedCard._cardId == 29) {
- // Interceptor cards are used to prevent collision
- actionDisplay(1330, 136, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (_selectedCard._cardId == 27) {
- actionDisplay(1330, 137, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- } else if (_gameBoardSide[0]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if (_gameBoardSide[0]._delayCard._cardId != 0) {
- actionDisplay(1330, 15, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!isAttackPossible(0, _selectedCard._cardId)) {
- switch (_selectedCard._cardId) {
- case 10:
- actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 12:
- actionDisplay(1330, 70, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- actionDisplay(1330, 82, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 17:
- actionDisplay(1330, 86, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 18:
- actionDisplay(1330, 88, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 19:
- actionDisplay(1330, 90, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- actionDisplay(1330, 92, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 21:
- actionDisplay(1330, 94, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- } else {
- playDelayCard(&_selectedCard, &_gameBoardSide[0]._delayCard);
- return;
- }
- } else if (_gameBoardSide[3]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if (_gameBoardSide[3]._delayCard._cardId != 0) {
- actionDisplay(1330, 17, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!isAttackPossible(3, _selectedCard._cardId)) {
- switch (_selectedCard._cardId) {
- case 10:
- actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 12:
- actionDisplay(1330, 70, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- actionDisplay(1330, 82, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 17:
- actionDisplay(1330, 86, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 18:
- actionDisplay(1330, 88, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 19:
- actionDisplay(1330, 90, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- actionDisplay(1330, 92, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 21:
- actionDisplay(1330, 94, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- } else {
- playDelayCard(&_selectedCard, &_gameBoardSide[3]._delayCard);
- return;
- }
- } else if (_gameBoardSide[1]._delayCard.isIn(Common::Point(_selectedCard._stationPos.x + 12, _selectedCard._stationPos.y + 12))) {
- if (_gameBoardSide[1]._delayCard._cardId != 0) {
- actionDisplay(1330, 19, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- } else if (!isAttackPossible(1, _selectedCard._cardId)) {
- switch (_selectedCard._cardId) {
- case 10:
- actionDisplay(1330, 66, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 12:
- actionDisplay(1330, 70, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 15:
- actionDisplay(1330, 82, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 17:
- actionDisplay(1330, 86, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 18:
- actionDisplay(1330, 88, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 19:
- actionDisplay(1330, 90, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 20:
- actionDisplay(1330, 92, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- case 21:
- actionDisplay(1330, 94, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- break;
- default:
- break;
- }
- } else {
- playDelayCard(&_selectedCard, &_gameBoardSide[1]._delayCard);
- return;
- }
- } else {
- actionDisplay(1330, 38, 159, 10, 1, 200, 0, 7, 0, 154, 154);
- }
- }
- } else {
- g_globals->_scenePalette.signalListeners();
- R2_GLOBALS._sceneObjects->draw();
- g_globals->_events.delay(g_globals->_sceneHandler->_delayTicks);
- }
-
- g_globals->_sceneObjects->recurse(SceneHandler::dispatchObject);
- }
-}
-
-void Scene1337::updateCursorId(int cursorId, bool updateFl) {
- if ((R2_GLOBALS._v57709 != 0) || (R2_GLOBALS._v5780C != 0))
- return;
-
- R2_GLOBALS._mouseCursorId = cursorId;
-
- if (updateFl) {
- R2_GLOBALS._mouseCursorId++;
-
- if (R2_GLOBALS._mouseCursorId < 1)
- R2_GLOBALS._mouseCursorId = 2;
-
- if (R2_GLOBALS._mouseCursorId > 2)
- R2_GLOBALS._mouseCursorId = 1;
- }
-
- // The original was using an intermediate function to call setCursorData.
- // It has been removed to improve readability
- if (R2_GLOBALS._mouseCursorId == 1) {
- R2_GLOBALS._v57810 = 200;
- setCursorData(5, 1, 4);
- } else if (R2_GLOBALS._mouseCursorId == 2) {
- R2_GLOBALS._v57810 = 300;
- setCursorData(5, 1, 5);
- } else {
- R2_GLOBALS._v57810 = 0;
- setCursorData(5, 0, 0);
- }
-}
-
-void Scene1337::setCursorData(int resNum, int rlbNum, int frameNum) {
- _cursorCurRes = resNum;
- _cursorCurStrip = rlbNum;
- _cursorCurFrame = frameNum;
-
- if (!frameNum) {
- // Should be a hardcoded cursor displaying only a dot.
- // FIXME: Use another cursor when possible
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
- } else {
- // TODO: The original was using some ressource caching, which was useless and complex
- // and which has been removed. This cursor behavior clearly made intensive use of this caching...
- // We now have to find a way to cache these cursor pointers and avoid loading them multiple times per seconds
- uint size;
- byte *cursor = g_resourceManager->getSubResource(resNum, rlbNum, frameNum, &size);
- // Decode the cursor
- GfxSurface s = surfaceFromRes(cursor);
-
- Graphics::Surface surface = s.lockSurface();
- const byte *cursorData = (const byte *)surface.getPixels();
- CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor);
- s.unlockSurface();
-
- DEALLOCATE(cursor);
- }
-}
-
-void Scene1337::subD18F5() {
- if (R2_GLOBALS._v57709 == 0)
- R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS);
-
- ++R2_GLOBALS._v57709;
-}
-
-void Scene1337::subD1917() {
- if (R2_GLOBALS._v57709 != 0) {
- R2_GLOBALS._v57709--;
- if (R2_GLOBALS._v57709 != 0) {
- // The original was using an intermediate function to call setCursorData.
- // It has been removed to improve readability
- setCursorData(5, _cursorCurStrip, _cursorCurFrame);
- }
- }
-}
-
-void Scene1337::subD1940(bool flag) {
- if (flag)
- ++R2_GLOBALS._v5780C;
- else if (R2_GLOBALS._v5780C != 0)
- --R2_GLOBALS._v5780C;
-}
-
-void Scene1337::subD1975(int arg1, int arg2) {
- warning("STUBBED lvl2 Scene1337::subD1975()");
-}
-
-void Scene1337::OptionsDialog::show() {
- OptionsDialog *dlg = new OptionsDialog();
- dlg->draw();
-
- // Show the dialog
- GfxButton *btn = dlg->execute(NULL);
-
- // Figure out the new selected character
- if (btn == &dlg->_quitGame)
- R2_GLOBALS._sceneManager.changeScene(125);
- else if (btn == &dlg->_restartGame)
- R2_GLOBALS._sceneManager.changeScene(1330);
-
- // Remove the dialog
- dlg->remove();
- delete dlg;
-}
-
-Scene1337::OptionsDialog::OptionsDialog() {
- // Set the elements text
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
- _autoplay.setText(scene->_autoplay ? AUTO_PLAY_ON : AUTO_PLAY_OFF);
- _restartGame.setText(START_NEW_CARD_GAME);
- _quitGame.setText(QUIT_CARD_GAME);
- _continueGame.setText(CONTINUE_CARD_GAME);
-
- // Set position of the elements
- _autoplay._bounds.moveTo(5, 2);
- _restartGame._bounds.moveTo(5, _autoplay._bounds.bottom + 2);
- _quitGame._bounds.moveTo(5, _restartGame._bounds.bottom + 2);
- _continueGame._bounds.moveTo(5, _quitGame._bounds.bottom + 2);
-
- // Add the items to the dialog
- addElements(&_autoplay, &_restartGame, &_quitGame, &_continueGame, NULL);
-
- // Set the dialog size and position
- frame();
- _bounds.collapse(-6, -6);
- setCenter(160, 100);
-}
-
-GfxButton *Scene1337::OptionsDialog::execute(GfxButton *defaultButton) {
- _gfxManager.activate();
-
- // Event loop
- GfxButton *selectedButton = NULL;
-
- bool breakFlag = false;
- while (!g_vm->shouldQuit() && !breakFlag) {
- Event event;
- while (g_globals->_events.getEvent(event) && !breakFlag) {
- // Adjust mouse positions to be relative within the dialog
- event.mousePos.x -= _gfxManager._bounds.left;
- event.mousePos.y -= _gfxManager._bounds.top;
-
- for (GfxElementList::iterator i = _elements.begin(); i != _elements.end(); ++i) {
- if ((*i)->process(event))
- selectedButton = static_cast<GfxButton *>(*i);
- }
-
- if (selectedButton == &_autoplay) {
- // Toggle Autoplay
- selectedButton = NULL;
- Scene1337 *scene = (Scene1337 *)R2_GLOBALS._sceneManager._scene;
- scene->_autoplay = !scene->_autoplay;
-
- _autoplay.setText(scene->_autoplay ? AUTO_PLAY_ON : AUTO_PLAY_OFF);
- _autoplay.draw();
- } else if (selectedButton) {
- breakFlag = true;
- break;
- } else if (!event.handled) {
- if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
- selectedButton = NULL;
- breakFlag = true;
- break;
- }
- }
- }
-
- g_system->delayMillis(10);
- GLOBALS._screenSurface.updateScreen();
- }
-
- _gfxManager.deactivate();
- return selectedButton;
-}
-
-/*--------------------------------------------------------------------------
* Scene 1500 - Cutscene: Ship landing
*
*--------------------------------------------------------------------------*/
@@ -13433,1796 +7970,5 @@ void Scene1945::signal() {
R2_GLOBALS._player._canWalk = false;
}
-/*--------------------------------------------------------------------------
- * Scene 1950 - Flup Tube Corridor Maze
- *
- *--------------------------------------------------------------------------*/
-
-Scene1950::KeypadWindow::KeypadWindow() {
- _buttonIndex = 0;
-}
-
-void Scene1950::KeypadWindow::synchronize(Serializer &s) {
- SceneArea::synchronize(s);
-
- s.syncAsSint16LE(_buttonIndex);
-}
-
-Scene1950::KeypadWindow::KeypadButton::KeypadButton() {
- _buttonIndex = 0;
- _pressed = false;
- _toggled = false;
-}
-
-void Scene1950::KeypadWindow::KeypadButton::synchronize(Serializer &s) {
- SceneActor::synchronize(s);
-
- s.syncAsSint16LE(_buttonIndex);
- s.syncAsSint16LE(_pressed);
- s.syncAsSint16LE(_toggled);
-}
-
-void Scene1950::KeypadWindow::KeypadButton::init(int indx) {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _buttonIndex = indx;
- _pressed = false;
- _toggled = false;
-
- postInit();
- setup(1971, 2, 1);
- fixPriority(249);
- setPosition(Common::Point(((_buttonIndex % 4) * 22) + 127, ((_buttonIndex / 4) * 19) + 71));
- scene->_sceneAreas.push_front(this);
-}
-
-void Scene1950::KeypadWindow::KeypadButton::process(Event &event) {
- if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE)
- && (_bounds.contains(event.mousePos)) && !_pressed) {
- R2_GLOBALS._sound2.play(227);
- if (!_toggled) {
- setFrame(2);
- _toggled = true;
- } else {
- setFrame(1);
- _toggled = false;
- }
- _pressed = true;
- event.handled = true;
- }
-
- if ((event.eventType == EVENT_BUTTON_UP) && _pressed) {
- _pressed = false;
- event.handled = true;
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- scene->doButtonPress(_buttonIndex);
- }
-}
-
-bool Scene1950::KeypadWindow::KeypadButton::startAction(CursorType action, Event &event) {
- if (action == CURSOR_USE)
- return false;
- return SceneActor::startAction(action, event);
-}
-
-void Scene1950::KeypadWindow::remove() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- for (_buttonIndex = 0; _buttonIndex < 16; ++_buttonIndex) {
- scene->_sceneAreas.remove(&_buttons[_buttonIndex]);
- _buttons[_buttonIndex].remove();
- }
-
- ModalWindow::remove();
-
- if (!R2_GLOBALS.getFlag(37))
- R2_GLOBALS._sound2.play(278);
-
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- scene->_eastExit._enabled = true;
-
- if (!R2_GLOBALS.getFlag(37)) {
- if (R2_GLOBALS.getFlag(36)) {
- scene->_sceneMode = 1964;
- scene->setAction(&scene->_sequenceManager, scene, 1964, &R2_GLOBALS._player, NULL);
- } else {
- scene->_sceneMode = 1965;
- scene->setAction(&scene->_sequenceManager, scene, 1965, &R2_GLOBALS._player, NULL);
- }
- }
-}
-
-void Scene1950::KeypadWindow::setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- if (R2_GLOBALS._player._mover)
- R2_GLOBALS._player.addMover(NULL);
- R2_GLOBALS._player._canWalk = false;
-
- ModalWindow::setup2(visage, stripFrameNum, frameNum, posX, posY);
-
- _object1.fixPriority(248);
- scene->_eastExit._enabled = false;
- setup3(1950, 27, 28, 27);
-
- for (_buttonIndex = 0; _buttonIndex < 16; _buttonIndex++)
- _buttons[_buttonIndex].init(_buttonIndex);
-}
-
-void Scene1950::KeypadWindow::setup3(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::LaserPanel::proc13()
- _areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
-}
-
-/*--------------------------------------------------------------------------*/
-
-bool Scene1950::Keypad::startAction(CursorType action, Event &event) {
- if ((action != CURSOR_USE) || (R2_GLOBALS.getFlag(37)))
- return SceneHotspot::startAction(action, event);
-
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS.getFlag(36)) {
- scene->_sceneMode = 1962;
- scene->setAction(&scene->_sequenceManager, scene, 1962, &R2_GLOBALS._player, NULL);
- } else {
- scene->_sceneMode = 1963;
- scene->setAction(&scene->_sequenceManager, scene, 1963, &R2_GLOBALS._player, NULL);
- }
- return true;
-}
-
-bool Scene1950::Door::startAction(CursorType action, Event &event) {
- if (action != R2_SCRITH_KEY)
- return SceneActor::startAction(action, event);
-
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- R2_GLOBALS._player.disableControl();
- R2_INVENTORY.setObjectScene(R2_SCRITH_KEY, 0);
- scene->_sceneMode = 1958;
- scene->setAction(&scene->_sequenceManager, scene, 1958, &R2_GLOBALS._player, &scene->_door, NULL);
- return true;
-}
-
-bool Scene1950::Scrolls::startAction(CursorType action, Event &event) {
- if ((action != CURSOR_USE) || (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) != 1950))
- return SceneActor::startAction(action, event);
-
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- R2_GLOBALS._player.disableControl();
- scene->_sceneMode = 1968;
- scene->setAction(&scene->_sequenceManager, scene, 1968, &R2_GLOBALS._player, NULL);
-
- return true;
-}
-
-bool Scene1950::Gem::startAction(CursorType action, Event &event) {
- if ((action != CURSOR_USE) || (!R2_GLOBALS.getFlag(37)))
- return SceneActor::startAction(action, event);
-
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- R2_GLOBALS._player.disableControl();
- scene->_sceneMode = 1967;
- scene->setAction(&scene->_sequenceManager, scene, 1967, &R2_GLOBALS._player, NULL);
-
- return true;
-}
-
-/*--------------------------------------------------------------------------*/
-
-Scene1950::Vampire::Vampire() {
- _deadPosition = Common::Point(0, 0);
- _deltaX = 0;
- _deltaY = 0;
- _vampireMode = 0;
-}
-
-void Scene1950::Vampire::synchronize(Serializer &s) {
- SceneActor::synchronize(s);
-
- s.syncAsSint16LE(_deadPosition.x);
- s.syncAsSint16LE(_deadPosition.y);
- s.syncAsSint16LE(_deltaX);
- s.syncAsSint16LE(_deltaY);
- s.syncAsSint16LE(_vampireMode);
-}
-
-void Scene1950::Vampire::signal() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- switch (_vampireMode) {
- case 19: {
- _vampireMode = 0;
- setVisage(1960);
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- setStrip(2);
- else
- setStrip(1);
-
- NpcMover *mover = new NpcMover();
- addMover(mover, &scene->_vampireDestPos, scene);
- }
- break;
- case 20: {
- // Non fatal shot
- _vampireMode = 19;
- R2_GLOBALS._player.setVisage(22);
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- R2_GLOBALS._player.setStrip(1);
- else
- R2_GLOBALS._player.setStrip(2);
- R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired--;
-
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- _deadPosition.x = _position.x + 10;
- else
- _deadPosition.x = _position.x - 10;
- _deadPosition.y = _position.y - 4;
-
- setVisage(1961);
-
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- setStrip(2);
- else
- setStrip(1);
-
- animate(ANIM_MODE_2, NULL);
- Common::Point pt = _deadPosition;
- PlayerMover *mover = new PlayerMover();
- addMover(mover, &pt, this);
-
- R2_GLOBALS._player.enableControl();
- }
- break;
- case 21: {
- // Fatal shot
- R2_GLOBALS._player.setVisage(22);
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- R2_GLOBALS._player.setStrip(1);
- else
- R2_GLOBALS._player.setStrip(2);
- R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
-
- setVisage(1961);
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- setStrip(4);
- else
- setStrip(3);
- setDetails(1950, 15, -1, 17, 2, (SceneItem *) NULL);
- addMover(NULL);
- _numFrames = 8;
- R2_GLOBALS._sound2.play(226);
- animate(ANIM_MODE_5, NULL);
- fixPriority(10);
-
- R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._isAlive = false;
- R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired--;
- R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._position = _position;
- _deltaX = (_position.x - R2_GLOBALS._player._position.x) / 2;
- _deltaY = (_position.y - R2_GLOBALS._player._position.y) / 2;
-
- byte vampireCount = 0;
- for (byte i = 0; i < 18; ++i) {
- if (!R2_GLOBALS._vampireData[i]._isAlive)
- ++vampireCount;
- }
-
- if (vampireCount == 18) {
- R2_GLOBALS.setFlag(36);
- _vampireMode = 23;
- Common::Point pt(R2_GLOBALS._player._position.x + _deltaX, R2_GLOBALS._player._position.y + _deltaY);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- } else if (vampireCount == 1) {
- _vampireMode = 22;
- Common::Point pt(R2_GLOBALS._player._position.x + _deltaX, R2_GLOBALS._player._position.y + _deltaY);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- } else {
- R2_GLOBALS._player.enableControl(CURSOR_WALK);
- }
-
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- scene->_eastExit._enabled = true;
- else
- scene->_westExit._enabled = true;
-
- scene->_vampireActive = false;
- }
- break;
- case 22:
- SceneItem::display(1950, 18, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- R2_GLOBALS._player.enableControl(CURSOR_WALK);
- break;
- case 23:
- SceneItem::display(1950, 25, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- scene->_sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- scene->setAction(&scene->_sequenceManager, scene, 1960, &R2_GLOBALS._player, NULL);
- break;
- default:
- break;
- }
-}
-
-bool Scene1950::Vampire::startAction(CursorType action, Event &event) {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- if (!R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._isAlive ||
- (action != R2_PHOTON_STUNNER))
- return SceneActor::startAction(action, event);
-
- R2_GLOBALS._player.disableControl();
-
- if (R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired <= 1)
- _vampireMode = 21;
- else
- _vampireMode = 20;
-
- R2_GLOBALS._player.setVisage(25);
- if (R2_GLOBALS._flubMazeEntryDirection == 3)
- R2_GLOBALS._player.setStrip(2);
- else
- R2_GLOBALS._player.setStrip(1);
- R2_GLOBALS._player.animate(ANIM_MODE_5, this);
- R2_GLOBALS._sound3.play(99);
-
- return true;
-}
-
-/*--------------------------------------------------------------------------*/
-
-void Scene1950::NorthExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 1;
- scene->_sceneMode = 11;
-
- Common::Point pt(160, 127);
- PlayerMover *mover = new PlayerMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
-}
-
-void Scene1950::UpExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 2;
- scene->_sceneMode = 12;
-
- if (!scene->_upExitStyle) {
- if (R2_GLOBALS.getFlag(36))
- scene->setAction(&scene->_sequenceManager, scene, 1953, &R2_GLOBALS._player, NULL);
- else
- scene->setAction(&scene->_sequenceManager, scene, 1970, &R2_GLOBALS._player, NULL);
- } else {
- if (R2_GLOBALS.getFlag(36))
- scene->setAction(&scene->_sequenceManager, scene, 1952, &R2_GLOBALS._player, NULL);
- else
- scene->setAction(&scene->_sequenceManager, scene, 1969, &R2_GLOBALS._player, NULL);
- }
-}
-
-void Scene1950::EastExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 3;
- scene->_sceneMode = 13;
-
- if (scene->_vampireActive)
- R2_GLOBALS._player.animate(ANIM_MODE_9);
-
- Common::Point pt(340, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
-}
-
-void Scene1950::DownExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 4;
- scene->_sceneMode = 14;
-
- if (R2_GLOBALS.getFlag(36))
- scene->setAction(&scene->_sequenceManager, scene, 1956, &R2_GLOBALS._player, NULL);
- else
- scene->setAction(&scene->_sequenceManager, scene, 1973, &R2_GLOBALS._player, NULL);
-}
-
-void Scene1950::SouthExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 5;
- scene->_sceneMode = 15;
-
- Common::Point pt(160, 213);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
-}
-
-void Scene1950::WestExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 6;
-
- if (R2_GLOBALS._flubMazeArea == 2) {
- // In the very first corridor area after the Scrith Door
- if ((R2_GLOBALS.getFlag(36)) && (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 2) && (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2)) {
- scene->_sceneMode = 1961;
- Common::Point pt(-20, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
- } else {
- if (!R2_GLOBALS.getFlag(36))
- SceneItem::display(1950, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- if ((R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950) || (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 1950))
- SceneItem::display(1950, 34, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- scene->_sceneMode = 0;
- Common::Point pt(30, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
- }
- } else {
- if (scene->_vampireActive)
- R2_GLOBALS._player.animate(ANIM_MODE_9);
-
- scene->_sceneMode = 16;
- Common::Point pt(-20, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
- }
-}
-
-void Scene1950::ShaftExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 0;
- scene->_sceneMode = 1951;
- scene->setAction(&scene->_sequenceManager, scene, 1951, &R2_GLOBALS._player, NULL);
-}
-
-void Scene1950::DoorExit::changeScene() {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
-
- _enabled = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._flubMazeEntryDirection = 3;
- if (R2_GLOBALS._player._visage == 22) {
- scene->_sceneMode = 1975;
- scene->setAction(&scene->_sequenceManager, scene, 1975, &R2_GLOBALS._player, NULL);
- } else {
- SceneItem::display(1950, 22, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- R2_GLOBALS._flubMazeEntryDirection = 0;
- scene->_sceneMode = 0;
- Common::Point pt(250, 150);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, scene);
- _enabled = true;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-Scene1950::Scene1950() {
- _upExitStyle = false;
- _removeFlag = false;
- _vampireActive = false;
- _vampireDestPos = Common::Point(0, 0);
- _vampireIndex = 0;
-}
-
-void Scene1950::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
-
- s.syncAsSint16LE(_upExitStyle);
- s.syncAsSint16LE(_removeFlag);
- s.syncAsSint16LE(_vampireActive);
- s.syncAsSint16LE(_vampireDestPos.x);
- s.syncAsSint16LE(_vampireDestPos.y);
- s.syncAsSint16LE(_vampireIndex);
-}
-
-void Scene1950::initArea() {
- _northExit._enabled = false;
- _upExit._enabled = false;
- _eastExit._enabled = false;
- _downExit._enabled = false;
- _southExit._enabled = false;
- _westExit._enabled = false;
- _shaftExit._enabled = false;
- _doorExit._enabled = false;
- _northExit._insideArea = false;
- _upExit._insideArea = false;
- _eastExit._insideArea = false;
- _downExit._insideArea = false;
- _southExit._insideArea = false;
- _westExit._insideArea = false;
- _shaftExit._insideArea = false;
- _doorExit._insideArea = false;
- _northExit._moving = false;
- _upExit._moving = false;
- _eastExit._moving = false;
- _downExit._moving = false;
- _southExit._moving = false;
- _westExit._moving = false;
- _shaftExit._moving = false;
- _doorExit._moving = false;
- _upExitStyle = false;
-
- switch (R2_GLOBALS._flubMazeArea - 1) {
- case 0:
- loadScene(1948);
- break;
- case 1:
- // No break on purpose
- case 8:
- // No break on purpose
- case 10:
- // No break on purpose
- case 12:
- // No break on purpose
- case 16:
- // No break on purpose
- case 19:
- // No break on purpose
- case 23:
- // No break on purpose
- case 30:
- // No break on purpose
- case 44:
- // No break on purpose
- case 72:
- // No break on purpose
- case 74:
- // No break on purpose
- case 86:
- // No break on purpose
- case 96:
- // No break on purpose
- case 103:
- loadScene(1950);
- break;
- case 2:
- // No break on purpose
- case 29:
- loadScene(1965);
- break;
- case 3:
- // No break on purpose
- case 9:
- // No break on purpose
- case 11:
- // No break on purpose
- case 15:
- // No break on purpose
- case 24:
- // No break on purpose
- case 39:
- // No break on purpose
- case 45:
- // No break on purpose
- case 71:
- // No break on purpose
- case 73:
- // No break on purpose
- case 75:
- // No break on purpose
- case 79:
- // No break on purpose
- case 85:
- // No break on purpose
- case 87:
- // No break on purpose
- case 95:
- loadScene(1955);
- break;
- case 4:
- // No break on purpose
- case 6:
- // No break on purpose
- case 13:
- // No break on purpose
- case 27:
- // No break on purpose
- case 41:
- // No break on purpose
- case 48:
- // No break on purpose
- case 50:
- // No break on purpose
- case 54:
- // No break on purpose
- case 76:
- // No break on purpose
- case 80:
- // No break on purpose
- case 90:
- // No break on purpose
- case 104:
- loadScene(1975);
- break;
- case 5:
- // No break on purpose
- case 7:
- // No break on purpose
- case 14:
- // No break on purpose
- case 28:
- // No break on purpose
- case 32:
- // No break on purpose
- case 47:
- // No break on purpose
- case 53:
- loadScene(1997);
- break;
- case 17:
- // No break on purpose
- case 20:
- // No break on purpose
- case 25:
- // No break on purpose
- case 31:
- // No break on purpose
- case 33:
- // No break on purpose
- case 46:
- loadScene(1995);
- break;
- case 18:
- // No break on purpose
- case 22:
- // No break on purpose
- case 26:
- // No break on purpose
- case 36:
- // No break on purpose
- case 38:
- // No break on purpose
- case 43:
- // No break on purpose
- case 51:
- // No break on purpose
- case 70:
- // No break on purpose
- case 78:
- // No break on purpose
- case 84:
- // No break on purpose
- case 89:
- // No break on purpose
- case 101:
- loadScene(1970);
- break;
- case 21:
- // No break on purpose
- case 34:
- // No break on purpose
- case 57:
- // No break on purpose
- case 58:
- // No break on purpose
- case 59:
- // No break on purpose
- case 62:
- // No break on purpose
- case 65:
- loadScene(1980);
- break;
- case 35:
- // No break on purpose
- case 61:
- // No break on purpose
- case 77:
- // No break on purpose
- case 83:
- loadScene(1982);
- break;
- case 37:
- // No break on purpose
- case 52:
- // No break on purpose
- case 82:
- // No break on purpose
- case 88:
- // No break on purpose
- case 92:
- // No break on purpose
- case 97:
- // No break on purpose
- case 100:
- loadScene(1962);
- break;
- case 40:
- // No break on purpose
- case 102:
- loadScene(1960);
- break;
- case 42:
- // No break on purpose
- case 55:
- // No break on purpose
- case 60:
- // No break on purpose
- case 66:
- // No break on purpose
- case 68:
- // No break on purpose
- case 69:
- // No break on purpose
- case 93:
- // No break on purpose
- case 98:
- loadScene(1990);
- break;
- case 49:
- // No break on purpose
- case 81:
- // No break on purpose
- case 91:
- // No break on purpose
- case 94:
- // No break on purpose
- case 99:
- loadScene(1967);
- break;
- case 56:
- // No break on purpose
- case 63:
- // No break on purpose
- case 64:
- // No break on purpose
- case 67:
- loadScene(1985);
- _upExitStyle = true;
- break;
- default:
- break;
- }
-
- if (R2_GLOBALS._flubMazeArea != 1)
- R2_GLOBALS._walkRegions.load(1950);
-
- switch (R2_GLOBALS._flubMazeArea - 1) {
- case 0:
- _shaftExit._enabled = true;
- if ((R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0) && (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950))
- _doorExit._enabled = true;
- R2_GLOBALS._walkRegions.disableRegion(2);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
- R2_GLOBALS._walkRegions.disableRegion(5);
- R2_GLOBALS._walkRegions.disableRegion(6);
- break;
- case 1:
- // No break on purpose
- case 2:
- // No break on purpose
- case 3:
- // No break on purpose
- case 8:
- // No break on purpose
- case 9:
- // No break on purpose
- case 10:
- // No break on purpose
- case 11:
- // No break on purpose
- case 12:
- // No break on purpose
- case 15:
- // No break on purpose
- case 16:
- // No break on purpose
- case 19:
- // No break on purpose
- case 23:
- // No break on purpose
- case 24:
- // No break on purpose
- case 29:
- // No break on purpose
- case 30:
- // No break on purpose
- case 39:
- // No break on purpose
- case 40:
- // No break on purpose
- case 44:
- // No break on purpose
- case 45:
- // No break on purpose
- case 71:
- // No break on purpose
- case 72:
- // No break on purpose
- case 73:
- // No break on purpose
- case 74:
- // No break on purpose
- case 75:
- // No break on purpose
- case 79:
- // No break on purpose
- case 85:
- // No break on purpose
- case 86:
- // No break on purpose
- case 87:
- // No break on purpose
- case 95:
- // No break on purpose
- case 96:
- // No break on purpose
- case 102:
- // No break on purpose
- case 103:
- _eastExit._enabled = true;
- _westExit._enabled = true;
- break;
- case 4:
- // No break on purpose
- case 6:
- // No break on purpose
- case 13:
- // No break on purpose
- case 17:
- // No break on purpose
- case 20:
- // No break on purpose
- case 25:
- // No break on purpose
- case 27:
- // No break on purpose
- case 31:
- // No break on purpose
- case 33:
- // No break on purpose
- case 37:
- // No break on purpose
- case 41:
- // No break on purpose
- case 46:
- // No break on purpose
- case 48:
- // No break on purpose
- case 50:
- // No break on purpose
- case 52:
- // No break on purpose
- case 54:
- // No break on purpose
- case 76:
- // No break on purpose
- case 80:
- // No break on purpose
- case 82:
- // No break on purpose
- case 88:
- // No break on purpose
- case 90:
- // No break on purpose
- case 92:
- // No break on purpose
- case 97:
- // No break on purpose
- case 100:
- // No break on purpose
- case 104:
- _westExit._enabled = true;
- R2_GLOBALS._walkRegions.disableRegion(6);
- R2_GLOBALS._walkRegions.disableRegion(9);
- break;
- case 5:
- // No break on purpose
- case 7:
- // No break on purpose
- case 14:
- // No break on purpose
- case 18:
- // No break on purpose
- case 22:
- // No break on purpose
- case 26:
- // No break on purpose
- case 28:
- // No break on purpose
- case 32:
- // No break on purpose
- case 36:
- // No break on purpose
- case 38:
- // No break on purpose
- case 43:
- // No break on purpose
- case 47:
- // No break on purpose
- case 49:
- // No break on purpose
- case 51:
- // No break on purpose
- case 53:
- // No break on purpose
- case 70:
- // No break on purpose
- case 78:
- // No break on purpose
- case 81:
- // No break on purpose
- case 84:
- // No break on purpose
- case 89:
- // No break on purpose
- case 91:
- // No break on purpose
- case 94:
- // No break on purpose
- case 99:
- // No break on purpose
- case 101:
- _eastExit._enabled = true;
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(7);
- R2_GLOBALS._walkRegions.disableRegion(13);
- break;
- default:
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(6);
- R2_GLOBALS._walkRegions.disableRegion(7);
- R2_GLOBALS._walkRegions.disableRegion(9);
- R2_GLOBALS._walkRegions.disableRegion(13);
- break;
- }
-
- _northDoorway.remove();
- _northDoorway.removeObject();
- _southDoorway.remove();
-
- switch (R2_GLOBALS._flubMazeArea - 4) {
- case 0:
- // No break on purpose
- case 3:
- // No break on purpose
- case 16:
- // No break on purpose
- case 22:
- // No break on purpose
- case 24:
- // No break on purpose
- case 32:
- // No break on purpose
- case 33:
- // No break on purpose
- case 45:
- // No break on purpose
- case 46:
- // No break on purpose
- case 48:
- // No break on purpose
- case 51:
- // No break on purpose
- case 56:
- // No break on purpose
- case 59:
- // No break on purpose
- case 67:
- // No break on purpose
- case 68:
- // No break on purpose
- case 70:
- // No break on purpose
- case 73:
- // No break on purpose
- case 82:
- // No break on purpose
- case 90:
- _northExit._enabled = true;
- _northDoorway.setup(1950, (R2_GLOBALS._flubMazeArea % 2) + 1, 1, 160, 137, 25);
- //visage,strip,frame,px,py,priority,effect
- _southDoorway.postInit();
- _southDoorway.setVisage(1950);
- _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
- _southDoorway.setFrame(2);
- _southDoorway.setPosition(Common::Point(160, 167));
- _southDoorway.fixPriority(220);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
- break;
- case 7:
- // No break on purpose
- case 10:
- // No break on purpose
- case 23:
- // No break on purpose
- case 29:
- // No break on purpose
- case 31:
- // No break on purpose
- case 39:
- // No break on purpose
- case 40:
- // No break on purpose
- case 52:
- // No break on purpose
- case 53:
- // No break on purpose
- case 55:
- // No break on purpose
- case 63:
- // No break on purpose
- case 65:
- // No break on purpose
- case 66:
- // No break on purpose
- case 75:
- // No break on purpose
- case 77:
- // No break on purpose
- case 81:
- // No break on purpose
- case 87:
- // No break on purpose
- case 89:
- // No break on purpose
- case 97:
- _southExit._enabled = true;
-
- _southDoorway.postInit();
- _southDoorway.setVisage(1950);
- _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
- _southDoorway.setFrame(3);
- _southDoorway.setPosition(Common::Point(160, 167));
- _southDoorway.fixPriority(220);
- break;
- case 58:
- // No break on purpose
- case 74:
- // No break on purpose
- case 80:
- _northExit._enabled = true;
- _southExit._enabled = true;
-
- _northDoorway.setup(1950, (R2_GLOBALS._flubMazeArea % 2) + 1, 1, 160, 137, 25);
-
- _southDoorway.postInit();
- _southDoorway.setVisage(1950);
- _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
- _southDoorway.setFrame(3);
- _southDoorway.setPosition(Common::Point(160, 167));
- _southDoorway.fixPriority(220);
- R2_GLOBALS._walkRegions.disableRegion(3);
- R2_GLOBALS._walkRegions.disableRegion(4);
- break;
- default:
- _southDoorway.postInit();
- _southDoorway.setVisage(1950);
- _southDoorway.setStrip(((R2_GLOBALS._flubMazeArea - 1) / 35) % 2 + 1);
- _southDoorway.setFrame(2);
- _southDoorway.setPosition(Common::Point(160, 167));
- _southDoorway.fixPriority(220);
- break;
- }
-
- switch (R2_GLOBALS._flubMazeArea - 3) {
- case 0:
- // No break on purpose
- case 3:
- // No break on purpose
- case 5:
- // No break on purpose
- case 12:
- // No break on purpose
- case 15:
- // No break on purpose
- case 18:
- // No break on purpose
- case 19:
- // No break on purpose
- case 23:
- // No break on purpose
- case 26:
- // No break on purpose
- case 27:
- // No break on purpose
- case 29:
- // No break on purpose
- case 30:
- // No break on purpose
- case 31:
- // No break on purpose
- case 32:
- // No break on purpose
- case 44:
- // No break on purpose
- case 45:
- // No break on purpose
- case 51:
- // No break on purpose
- case 55:
- // No break on purpose
- case 56:
- // No break on purpose
- case 57:
- // No break on purpose
- case 60:
- // No break on purpose
- case 63:
- _upExit._enabled = true;
- break;
- case 54:
- // No break on purpose
- case 61:
- // No break on purpose
- case 62:
- // No break on purpose
- case 65:
- _upExit._enabled = true;
- // No break on purpose
- case 35:
- // No break on purpose
- case 38:
- // No break on purpose
- case 40:
- // No break on purpose
- case 47:
- // No break on purpose
- case 50:
- // No break on purpose
- case 53:
- // No break on purpose
- case 58:
- // No break on purpose
- case 64:
- // No break on purpose
- case 66:
- // No break on purpose
- case 67:
- // No break on purpose
- case 79:
- // No break on purpose
- case 80:
- // No break on purpose
- case 86:
- // No break on purpose
- case 89:
- // No break on purpose
- case 90:
- // No break on purpose
- case 91:
- // No break on purpose
- case 92:
- // No break on purpose
- case 95:
- // No break on purpose
- case 96:
- // No break on purpose
- case 97:
- // No break on purpose
- case 98:
- // No break on purpose
- case 100:
- _downExit._enabled = true;
- R2_GLOBALS._walkRegions.disableRegion(4);
- R2_GLOBALS._walkRegions.disableRegion(5);
- R2_GLOBALS._walkRegions.disableRegion(6);
- R2_GLOBALS._walkRegions.disableRegion(10);
- R2_GLOBALS._walkRegions.disableRegion(11);
- default:
- break;
- }
- R2_GLOBALS._uiElements.draw();
-}
-
-void Scene1950::enterArea() {
- R2_GLOBALS._player.disableControl();
- R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
-
- _vampire.remove();
- _door.remove();
- _scrolls.remove();
-
- _vampireActive = false;
- _vampireIndex = 0;
-
- // Certain areas have a vampire in them
- switch (R2_GLOBALS._flubMazeArea) {
- case 10:
- _vampireIndex = 1;
- break;
- case 13:
- _vampireIndex = 2;
- break;
- case 16:
- _vampireIndex = 3;
- break;
- case 17:
- _vampireIndex = 4;
- break;
- case 24:
- _vampireIndex = 5;
- break;
- case 25:
- _vampireIndex = 6;
- break;
- case 31:
- _vampireIndex = 7;
- break;
- case 40:
- _vampireIndex = 8;
- break;
- case 45:
- _vampireIndex = 9;
- break;
- case 46:
- _vampireIndex = 10;
- break;
- case 73:
- _vampireIndex = 11;
- break;
- case 75:
- _vampireIndex = 12;
- break;
- case 80:
- _vampireIndex = 13;
- break;
- case 87:
- _vampireIndex = 14;
- break;
- case 88:
- _vampireIndex = 15;
- break;
- case 96:
- _vampireIndex = 16;
- break;
- case 97:
- _vampireIndex = 17;
- break;
- case 104:
- _vampireIndex = 18;
- break;
- default:
- break;
- }
-
- if (_vampireIndex != 0) {
- _vampire.postInit();
- _vampire._numFrames = 6;
- _vampire._moveRate = 6;
- _vampire._moveDiff = Common::Point(3, 2);
- _vampire._effect = EFFECT_SHADED;
-
- if (!R2_GLOBALS._vampireData[_vampireIndex - 1]._isAlive) {
- // Show vampire ashes
- _vampire.setPosition(Common::Point(R2_GLOBALS._vampireData[_vampireIndex - 1]._position));
- _vampire.animate(ANIM_MODE_NONE, NULL);
- _vampire.addMover(NULL);
- _vampire.setVisage(1961);
- _vampire.setStrip(4);
- _vampire.setFrame(10);
- _vampire.fixPriority(10);
- _vampire.setDetails(1950, 15, -1, 17, 2, (SceneItem *) NULL);
- } else {
- // Start the vampire
- _vampire.setVisage(1960);
- _vampire.setPosition(Common::Point(160, 130));
- _vampire.animate(ANIM_MODE_2, NULL);
- _vampire.setDetails(1950, 12, -1, 14, 2, (SceneItem *) NULL);
- _vampireActive = true;
- }
- }
- if ((R2_GLOBALS._flubMazeArea == 1) && (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) != 0)) {
- // Show doorway at the right hand side of the very first flub corridor
- _door.postInit();
- _door.setVisage(1948);
- _door.setStrip(3);
- _door.setPosition(Common::Point(278, 155));
- _door.fixPriority(100);
- _door.setDetails(1950, 19, 20, 23, 2, (SceneItem *) NULL);
- }
-
- if (R2_GLOBALS._flubMazeArea == 102) {
- R2_GLOBALS._walkRegions.load(1951);
- R2_GLOBALS._walkRegions.disableRegion(1);
- R2_GLOBALS._walkRegions.disableRegion(5);
- R2_GLOBALS._walkRegions.disableRegion(6);
- R2_GLOBALS._walkRegions.disableRegion(7);
-
- _cube.postInit();
- _cube.setVisage(1970);
- _cube.setStrip(1);
- if (R2_GLOBALS.getFlag(37))
- _cube.setFrame(3);
- else
- _cube.setFrame(1);
- _cube.setPosition(Common::Point(193, 158));
- _cube.setDetails(1950, 3, 4, 5, 2, (SceneItem *) NULL);
-
- _pulsingLights.postInit();
- _pulsingLights.setVisage(1970);
- _pulsingLights.setStrip(3);
- _pulsingLights.animate(ANIM_MODE_2, NULL);
- _pulsingLights._numFrames = 6;
- _pulsingLights.setPosition(Common::Point(194, 158));
- _pulsingLights.fixPriority(159);
-
- _keypad.setDetails(Rect(188, 124, 199, 133), 1950, 27, 28, -1, 2, NULL);
-
- if (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950) {
- _gem.postInit();
- _gem.setVisage(1970);
- _gem.setStrip(1);
- _gem.setFrame(2);
- _gem.fixPriority(160);
- }
-
- if (R2_GLOBALS.getFlag(37)) {
- _gem.setPosition(Common::Point(192, 118));
- _gem.setDetails(1950, 9, 4, -1, 2, (SceneItem *) NULL);
- } else {
- _containmentField.postInit();
- _containmentField.setVisage(1970);
- _containmentField.setStrip(4);
- _containmentField._numFrames = 4;
- _containmentField.animate(ANIM_MODE_8, 0, NULL);
- _containmentField.setPosition(Common::Point(192, 121));
- _containmentField.fixPriority(159);
- _containmentField.setDetails(1950, 6, 7, 8, 2, (SceneItem *) NULL);
-
- _gem.setPosition(Common::Point(192, 109));
- _gem.setDetails(1950, 9, 7, 8, 2, (SceneItem *) NULL);
- }
-
- _scrolls.postInit();
- _scrolls.setVisage(1972);
- _scrolls.setStrip(1);
- _scrolls.setPosition(Common::Point(76, 94));
- _scrolls.fixPriority(25);
- _scrolls.setDetails(1950, 30, -1, -1, 2, (SceneItem *) NULL);
- if (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2)
- _scrolls.setFrame(2);
- else
- _scrolls.setFrame(1);
-
- _removeFlag = true;
- } else if (_removeFlag) {
- _cube.remove();
- _containmentField.remove();
- _gem.remove();
- _pulsingLights.remove();
- _scrolls.remove();
-
- R2_GLOBALS._sceneItems.remove(&_background);
- _background.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 2, NULL);
-
- _removeFlag = false;
- }
-
- switch (R2_GLOBALS._flubMazeEntryDirection) {
- case 0:
- _sceneMode = 1950;
- if (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0)
- // The original uses CURSOR_ARROW. CURSOR_WALK is much more coherent
- R2_GLOBALS._player.enableControl(CURSOR_WALK);
- else
- setAction(&_sequenceManager, this, 1950, &R2_GLOBALS._player, NULL);
-
- break;
- case 1: {
- _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- R2_GLOBALS._player.setPosition(Common::Point(160, 213));
- Common::Point pt(160, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- }
- break;
- case 2:
- _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- if (R2_GLOBALS.getFlag(36))
- setAction(&_sequenceManager, this, 1957, &R2_GLOBALS._player, NULL);
- else
- setAction(&_sequenceManager, this, 1974, &R2_GLOBALS._player, NULL);
- break;
- case 3:
- // Entering from the left
- if (!_vampireActive) {
- _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- R2_GLOBALS._player.setPosition(Common::Point(-20, 160));
- Common::Point pt(30, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- } else {
- _sceneMode = 18;
- _eastExit._enabled = false;
- _vampireDestPos = Common::Point(60, 152);
- R2_GLOBALS._player.enableControl(CURSOR_USE);
- R2_GLOBALS._player._canWalk = false;
-
- _vampire.setStrip(2);
- NpcMover *mover = new NpcMover();
- _vampire.addMover(mover, &_vampireDestPos, this);
-
- R2_GLOBALS._player.setPosition(Common::Point(-20, 160));
- Common::Point pt2(30, 160);
- NpcMover *mover2 = new NpcMover();
- R2_GLOBALS._player.addMover(mover2, &pt2, NULL);
- }
- break;
- case 4:
- _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- if (!_upExitStyle) {
- if (R2_GLOBALS.getFlag(36))
- setAction(&_sequenceManager, this, 1955, &R2_GLOBALS._player, NULL);
- else
- setAction(&_sequenceManager, this, 1972, &R2_GLOBALS._player, NULL);
- } else {
- if (R2_GLOBALS.getFlag(36))
- setAction(&_sequenceManager, this, 1954, &R2_GLOBALS._player, NULL);
- else
- setAction(&_sequenceManager, this, 1971, &R2_GLOBALS._player, NULL);
- }
- break;
- case 5: {
- _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- R2_GLOBALS._player.setPosition(Common::Point(160, 127));
- Common::Point pt(160, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- }
- break;
- case 6:
- // Entering from the right
- if (!_vampireActive) {
- _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
- if (R2_GLOBALS._flubMazeArea == 1) {
- setAction(&_sequenceManager, this, 1961, &R2_GLOBALS._player, NULL);
- } else {
- R2_GLOBALS._player.setPosition(Common::Point(340, 160));
- Common::Point pt(289, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- }
- } else {
- _sceneMode = 17;
- _westExit._enabled = false;
- _vampireDestPos = Common::Point(259, 152);
-
- R2_GLOBALS._player.enableControl(CURSOR_USE);
- R2_GLOBALS._player._canWalk = false;
-
- _vampire.setStrip(1);
- NpcMover *mover = new NpcMover();
- _vampire.addMover(mover, &_vampireDestPos, this);
-
- R2_GLOBALS._player.setPosition(Common::Point(340, 160));
- Common::Point pt2(289, 160);
- NpcMover *mover2 = new NpcMover();
- R2_GLOBALS._player.addMover(mover2, &pt2, NULL);
- }
- break;
- default:
- break;
- }
-}
-
-void Scene1950::doButtonPress(int indx) {
- Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
- R2_GLOBALS._player.disableControl();
-
- int prevIndex = indx - 1;
- if ((indx / 4) == (prevIndex / 4)) {
- if (prevIndex < 0)
- prevIndex = 3;
- } else {
- prevIndex += 4;
- }
-
- assert(prevIndex >= 0 && prevIndex < 16);
- if (!_KeypadWindow._buttons[prevIndex]._toggled) {
- _KeypadWindow._buttons[prevIndex].setFrame(2);
- _KeypadWindow._buttons[prevIndex]._toggled = true;
- } else {
- _KeypadWindow._buttons[prevIndex].setFrame(1);
- _KeypadWindow._buttons[prevIndex]._toggled = false;
- }
-
- prevIndex = indx + 1;
- if ((indx / 4) == (prevIndex / 4)) {
- if (prevIndex > 15)
- prevIndex = 12;
- } else {
- prevIndex -= 4;
- }
-
- assert(prevIndex >= 0 && prevIndex < 16);
- if (!_KeypadWindow._buttons[prevIndex]._toggled) {
- _KeypadWindow._buttons[prevIndex].setFrame(2);
- _KeypadWindow._buttons[prevIndex]._toggled = true;
- } else {
- _KeypadWindow._buttons[prevIndex].setFrame(1);
- _KeypadWindow._buttons[prevIndex]._toggled = false;
- }
-
- prevIndex = indx - 4;
- if (prevIndex < 0)
- prevIndex += 16;
-
- assert(prevIndex >= 0 && prevIndex < 16);
- if (!_KeypadWindow._buttons[prevIndex]._toggled) {
- _KeypadWindow._buttons[prevIndex].setFrame(2);
- _KeypadWindow._buttons[prevIndex]._toggled = true;
- } else {
- _KeypadWindow._buttons[prevIndex].setFrame(1);
- _KeypadWindow._buttons[prevIndex]._toggled = false;
- }
-
- prevIndex = indx + 4;
- if (prevIndex > 15)
- prevIndex -= 16;
-
- assert(prevIndex >= 0 && prevIndex < 16);
- if (!_KeypadWindow._buttons[prevIndex]._toggled) {
- _KeypadWindow._buttons[prevIndex].setFrame(2);
- _KeypadWindow._buttons[prevIndex]._toggled = true;
- } else {
- _KeypadWindow._buttons[prevIndex].setFrame(1);
- _KeypadWindow._buttons[prevIndex]._toggled = false;
- }
-
- // Check whether all the buttons are highlighted
- int cpt = 0;
- for (prevIndex = 0; prevIndex < 16; prevIndex++) {
- if (_KeypadWindow._buttons[prevIndex]._toggled)
- ++cpt;
- }
-
- if (cpt != 16) {
- R2_GLOBALS._player.enableControl();
- R2_GLOBALS._player._canWalk = false;
- } else {
- R2_GLOBALS.setFlag(37);
- _sceneMode = 24;
- setAction(&_sequenceManager, scene, 1976, NULL);
- }
-}
-
-void Scene1950::postInit(SceneObjectList *OwnerList) {
- _upExitStyle = false;
- _removeFlag = false;
- _vampireActive = false;
- _vampireIndex = 0;
- if (R2_GLOBALS._sceneManager._previousScene == 300)
- R2_GLOBALS._flubMazeArea = 103;
-
- initArea();
- SceneExt::postInit();
- R2_GLOBALS._sound1.play(105);
-
- _northExit.setDetails(Rect(130, 46, 189, 135), SHADECURSOR_UP, 1950);
- _northExit.setDest(Common::Point(160, 145));
-
- _upExit.setDetails(Rect(208, 0, 255, 73), EXITCURSOR_N, 1950);
- _upExit.setDest(Common::Point(200, 151));
-
- _eastExit.setDetails(Rect(305, 95, 320, 147), EXITCURSOR_E, 1950);
- _eastExit.setDest(Common::Point(312, 160));
-
- _downExit.setDetails(Rect(208, 99, 255, 143), EXITCURSOR_S, 1950);
- _downExit.setDest(Common::Point(200, 151));
-
- _southExit.setDetails(Rect(113, 154, 206, 168), SHADECURSOR_DOWN, 1950);
- _southExit.setDest(Common::Point(160, 165));
-
- _westExit.setDetails(Rect(0, 95, 14, 147), EXITCURSOR_W, 1950);
- _westExit.setDest(Common::Point(7, 160));
-
- _shaftExit.setDetails(Rect(72, 54, 120, 128), EXITCURSOR_NW, 1950);
- _shaftExit.setDest(Common::Point(120, 140));
-
- _doorExit.setDetails(Rect(258, 60, 300, 145), EXITCURSOR_NE, 1950);
- _doorExit.setDest(Common::Point(268, 149));
-
- R2_GLOBALS._player.postInit();
- if ( (R2_INVENTORY.getObjectScene(R2_TANNER_MASK) == 0) && (R2_INVENTORY.getObjectScene(R2_PURE_GRAIN_ALCOHOL) == 0)
- && (R2_INVENTORY.getObjectScene(R2_SOAKED_FACEMASK) == 0) && (!R2_GLOBALS.getFlag(36)) )
- R2_GLOBALS._player.setVisage(22);
- else
- R2_GLOBALS._player.setVisage(20);
-
- R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
- _background.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 1, NULL);
-
- enterArea();
-}
-
-void Scene1950::remove() {
- R2_GLOBALS._sound1.stop();
- R2_GLOBALS._sound2.fadeOut2(NULL);
- SceneExt::remove();
-}
-
-void Scene1950::signal() {
- switch (_sceneMode) {
- case 11:
- R2_GLOBALS._flubMazeArea += 7;
- initArea();
- enterArea();
- break;
- case 12:
- // Moving up a ladder within the Flub maze
- R2_GLOBALS._flubMazeArea += 35;
- initArea();
- enterArea();
- break;
- case 1975:
- SceneItem::display(1950, 21, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, 1,
- SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
- // No break on purpose
- case 13:
- // Moving east within the Flub maze
- ++R2_GLOBALS._flubMazeArea;
- initArea();
- enterArea();
- break;
- case 14:
- // Moving down a ladder within the Flub maze
- R2_GLOBALS._flubMazeArea -= 35;
- initArea();
- enterArea();
- break;
- case 15:
- R2_GLOBALS._flubMazeArea -= 7;
- initArea();
- enterArea();
- break;
- case 16:
- // Moving west within the Flub maze
- // No break on purpose
- case 1961:
- --R2_GLOBALS._flubMazeArea;
- initArea();
- enterArea();
- break;
- case 17: {
- _sceneMode = 13;
- R2_GLOBALS._flubMazeEntryDirection = 3;
- _vampireActive = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._player._canWalk = true;
- R2_GLOBALS._player.setVisage(22);
- R2_GLOBALS._player.animate(ANIM_MODE_9);
- Common::Point pt(340, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- Common::Point pt2(289, 160);
- NpcMover *mover2 = new NpcMover();
- _vampire.addMover(mover2, &pt2, NULL);
- }
- break;
- case 18: {
- _sceneMode = 16;
- R2_GLOBALS._flubMazeEntryDirection = 6;
- _vampireActive = false;
- R2_GLOBALS._player.disableControl(CURSOR_WALK);
- R2_GLOBALS._player._canWalk = true;
- R2_GLOBALS._player.setVisage(22);
- R2_GLOBALS._player.animate(ANIM_MODE_9);
- Common::Point pt(-20, 160);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- Common::Point pt2(30, 160);
- NpcMover *mover2 = new NpcMover();
- _vampire.addMover(mover2, &pt2, NULL);
- }
- break;
- case 24:
- _KeypadWindow.remove();
- _sceneMode = 1966;
- _cube.setFrame(3);
- setAction(&_sequenceManager, this, 1966, &_containmentField, &_gem, NULL);
- break;
- case 1951:
- R2_GLOBALS._sound1.fadeOut2(NULL);
- R2_GLOBALS._sceneManager.changeScene(1945);
- break;
- case 1958:
- SceneItem::display(1950, 24, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
- R2_GLOBALS._player.enableControl(CURSOR_WALK);
- _doorExit._enabled = true;
- break;
- case 1959:
- R2_INVENTORY.setObjectScene(R2_SOAKED_FACEMASK, 0);
- R2_GLOBALS._player.enableControl(CURSOR_WALK);
- _doorExit._enabled = true;
- break;
- case 1962:
- // No break on purpose
- case 1963:
- R2_GLOBALS._player.enableControl();
- _KeypadWindow.setup2(1971, 1, 1, 160, 135);
- break;
- case 1964:
- // No break on purpose
- case 1965:
- if (!R2_GLOBALS.getFlag(37))
- SceneItem::display(1950, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
-
- R2_GLOBALS._player.enableControl();
- break;
- case 1966:
- _containmentField.remove();
- if (R2_GLOBALS.getFlag(36)) {
- _sceneMode = 1964;
- setAction(&_sequenceManager, this, 1964, &R2_GLOBALS._player, NULL);
- } else {
- _sceneMode = 1965;
- setAction(&_sequenceManager, this, 1965, &R2_GLOBALS._player, NULL);
- }
- _gem.setDetails(1950, 9, -1, -1, 2, (SceneItem *) NULL);
- break;
- case 1967: {
- _sceneMode = 0;
- R2_INVENTORY.setObjectScene(R2_SAPPHIRE_BLUE, 2);
- _gem.remove();
- if (R2_GLOBALS.getFlag(36))
- R2_GLOBALS._player.setVisage(20);
- else
- R2_GLOBALS._player.setVisage(22);
-
- R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- // This is a hack to work around a pathfinding issue. original destination is (218, 165)
- Common::Point pt(128, 165);
- NpcMover *mover = new NpcMover();
- R2_GLOBALS._player.addMover(mover, &pt, this);
- }
- break;
- case 1968:
- R2_GLOBALS._player.enableControl();
- R2_INVENTORY.setObjectScene(R2_ANCIENT_SCROLLS, 2);
- _scrolls.setFrame(2);
- if (R2_GLOBALS.getFlag(36))
- R2_GLOBALS._player.setVisage(20);
- else
- R2_GLOBALS._player.setVisage(22);
- R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
- break;
- default:
- R2_GLOBALS._player.enableControl(CURSOR_WALK);
- break;
- }
-}
-
-void Scene1950::process(Event &event) {
- if ( (event.eventType == EVENT_BUTTON_DOWN)
- && (R2_GLOBALS._player._uiEnabled)
- && (R2_GLOBALS._events.getCursor() == R2_SOAKED_FACEMASK)
- && (R2_GLOBALS._player._bounds.contains(event.mousePos))
- && (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0)) {
- event.handled = true;
- R2_GLOBALS._player.disableControl();
- _shaftExit._enabled = false;
- _doorExit._enabled = false;
- _sceneMode = 1959;
- setAction(&_sequenceManager, this, 1959, &R2_GLOBALS._player, NULL);
- }
-
- Scene::process(event);
-}
-
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h
index 91c4b88391..e6f5e0ab97 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.h
@@ -135,270 +135,6 @@ public:
virtual void saveCharacter(int characterIndex);
};
-class Scene1200 : public SceneExt {
- enum CrawlDirection { CRAWL_EAST = 1, CRAWL_WEST = 2, CRAWL_SOUTH = 3, CRAWL_NORTH = 4 };
-
- class LaserPanel: public ModalWindow {
- public:
- class Jumper : public SceneActorExt {
- public:
- void init(int state);
- virtual bool startAction(CursorType action, Event &event);
- };
-
- Jumper _jumper1;
- Jumper _jumper2;
- Jumper _jumper3;
-
- LaserPanel();
-
- virtual void postInit(SceneObjectList *OwnerList = NULL);
- virtual void remove();
- };
-
-public:
- NamedHotspot _item1;
- SceneActor _actor1;
- LaserPanel _laserPanel;
- MazeUI _mazeUI;
- SequenceManager _sequenceManager;
-
- int _nextCrawlDirection;
- int _field414;
- int _field416;
- int _field418;
- int _field41A;
- bool _fixupMaze;
-
- Scene1200();
- void synchronize(Serializer &s);
-
- void startCrawling(CrawlDirection dir);
-
- virtual void postInit(SceneObjectList *OwnerList = NULL);
- virtual void signal();
- virtual void process(Event &event);
- virtual void dispatch();
- virtual void saveCharacter(int characterIndex);
-};
-
-class Scene1337 : public SceneExt {
- class OptionsDialog: public GfxDialog {
- private:
- GfxButton _autoplay;
- GfxButton _restartGame;
- GfxButton _quitGame;
- GfxButton _continueGame;
-
- OptionsDialog();
- virtual ~OptionsDialog() {}
- virtual GfxButton *execute(GfxButton *defaultButton);
- public:
- static void show();
- };
-
- class Card: public SceneHotspot {
- public:
- SceneObject _card;
-
- int _cardId;
- Common::Point _stationPos;
-
- Card();
- void synchronize(Serializer &s);
- bool isIn(Common::Point pt);
- };
-
- class GameBoardSide: public SceneHotspot {
- public:
- Card _handCard[4];
- Card _outpostStation[8];
- Card _delayCard;
- Card _emptyStationPos;
-
- Common::Point _card1Pos;
- Common::Point _card2Pos;
- Common::Point _card3Pos;
- Common::Point _card4Pos;
- int _frameNum;
-
- GameBoardSide();
- void synchronize(Serializer &s);
- };
-
- class Action1337: public Action {
- public:
- void waitFrames(int32 frameCount);
- };
-
- class Action1: public Action1337 {
- public:
- void signal();
- };
- class Action2: public Action1337 {
- public:
- void signal();
- };
- class Action3: public Action1337 {
- public:
- void signal();
- };
- class Action4: public Action1337 {
- public:
- void signal();
- };
- class Action5: public Action1337 {
- public:
- void signal();
- };
- class Action6: public Action1337 {
- public:
- void signal();
- };
- class Action7: public Action1337 {
- public:
- void signal();
- };
- class Action8: public Action1337 {
- public:
- void signal();
- };
- class Action9: public Action1337 {
- public:
- void signal();
- };
- class Action10: public Action1337 {
- public:
- void signal();
- };
- class Action11: public Action1337 {
- public:
- void signal();
- };
- class Action12: public Action1337 {
- public:
- void signal();
- };
- class Action13: public Action1337 {
- public:
- void signal();
- };
-public:
- Action1 _action1;
- Action2 _action2;
- Action3 _action3;
- Action4 _action4;
- Action5 _action5;
- Action6 _action6;
- Action7 _action7;
- Action8 _action8;
- Action9 _action9;
- Action10 _action10;
- Action11 _action11;
- Action12 _action12;
- Action13 _action13;
-
- typedef void (Scene1337::*FunctionPtrType)();
- FunctionPtrType _delayedFunction;
-
- bool _autoplay;
- bool _shuffleEndedFl;
- bool _showPlayerTurn;
- bool _displayHelpFl;
- bool _instructionsDisplayedFl;
-
- // Discarded cards are put in the available cards pile, with an higher index so there no conflict
- int _currentDiscardIndex;
- int _availableCardsPile[100];
- int _cardsAvailableNumb;
- int _currentPlayerNumb;
- int _actionIdx1;
- int _actionIdx2;
- int _winnerId;
- int _instructionsWaitCount;
- int _cursorCurRes;
- int _cursorCurStrip;
- int _cursorCurFrame;
-
- ASound _aSound1;
- ASound _aSound2;
- GameBoardSide _gameBoardSide[4];
- SceneActor _helpIcon;
- SceneActor _stockPile;
- SceneItem _actionItem;
- SceneObject _currentPlayerArrow;
-
- Card *_actionCard1;
- Card *_actionCard2;
- Card *_actionCard3;
- Card _animatedCard;
- Card _shuffleAnimation;
- Card _discardedPlatformCard;
- Card _selectedCard;
- Card _discardPile;
- Card _stockCard;
-
- SceneObject _upperDisplayCard[8];
- SceneObject _lowerDisplayCard[8];
-
- Scene1337();
- virtual void synchronize(Serializer &s);
-
- void actionDisplay(int resNum, int lineNum, int x, int y, int keepOnScreen, int width, int textMode, int fontNum, int colFG, int colBGExt, int colFGExt);
- void setAnimationInfo(Card *card);
- void handleNextTurn();
- void handlePlayerTurn();
- bool isStationCard(int cardId);
- bool isStopConstructionCard(int cardId);
- int getStationId(int playerId, int handCardId);
- int findPlatformCardInHand(int playerId);
- int findCard13InHand(int playerId);
- int checkThieftCard(int playerId);
- int isDelayCard(int cardId);
- int getStationCardId(int cardId);
- void handlePlayer01Discard(int playerId);
- void playThieftCard(int playerId, Card *card, int victimId);
- int getPreventionCardId(int cardId);
- bool isAttackPossible(int victimId, int cardId);
- int getPlayerWithOutpost(int playerId);
- bool checkAntiDelayCard(int delayCardId, int cardId);
- void playStationCard(Card *station, Card *platform);
- void playDelayCard(Card *card, Card *dest);
- void playPlatformCard(Card *card, Card *dest);
- void playAntiDelayCard(Card *card, Card *dest);
- Card *getStationCard(int arg1);
- void playCounterTrickCard(Card *card, int playerId);
- int getFreeHandCard(int playerId);
- void discardCard(Card *card);
- void subC4CD2();
- void subC4CEC();
- void subC51A0(Card *subObj1, Card *subObj2);
- void displayDialog(int dialogNumb);
- void subPostInit();
- void displayInstructions();
- void suggestInstructions();
- void shuffleCards();
- void dealCards();
- void showOptionsDialog();
- void handleClick(int arg1, Common::Point pt);
- void handlePlayer0();
- void handlePlayer1();
- void handlePlayer2();
- void handlePlayer3();
- void handleAutoplayPlayer2();
- void updateCursorId(int arg1, bool arg2);
- void setCursorData(int resNum, int rlbNum, int frameNum);
- void subD18F5();
- void subD1917();
- void subD1940(bool flag);
- void subD1975(int arg1, int arg2);
-
- virtual void postInit(SceneObjectList *OwnerList = NULL);
- virtual void remove();
- virtual void process(Event &event);
- virtual void dispatch();
-};
-
class Scene1500 : public SceneExt {
public:
SceneActor _starship;
@@ -1097,143 +833,6 @@ public:
virtual void signal();
};
-class Scene1950 : public SceneExt {
- /* Windows */
- class KeypadWindow: public ModalWindow {
- public:
- class KeypadButton : public SceneActor {
- public:
- int _buttonIndex;
- bool _pressed;
- bool _toggled;
-
- KeypadButton();
- void synchronize(Serializer &s);
-
- void init(int indx);
- virtual void process(Event &event);
- virtual bool startAction(CursorType action, Event &event);
- };
-
- SceneActor _areaActor;
- KeypadButton _buttons[16];
-
- int _buttonIndex;
-
- KeypadWindow();
- virtual void synchronize(Serializer &s);
- virtual void remove();
- virtual void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY);
- virtual void setup3(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
- };
-
- class Keypad : public NamedHotspot {
- public:
- virtual bool startAction(CursorType action, Event &event);
- };
-
- /* Actors */
- class Door : public SceneActor {
- public:
- virtual bool startAction(CursorType action, Event &event);
- };
- class Scrolls : public SceneActor {
- public:
- virtual bool startAction(CursorType action, Event &event);
- };
- class Gem : public SceneActor {
- public:
- virtual bool startAction(CursorType action, Event &event);
- };
- class Vampire : public SceneActor {
- public:
- Common::Point _deadPosition;
- int _deltaX;
- int _deltaY;
- int _vampireMode;
-
- Vampire();
- void synchronize(Serializer &s);
-
- virtual void signal();
- virtual bool startAction(CursorType action, Event &event);
- };
-
- /* Exits */
- class NorthExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class UpExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class EastExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class DownExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class SouthExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class WestExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class ShaftExit : public SceneExit {
- public:
- virtual void changeScene();
- };
- class DoorExit : public SceneExit {
- public:
- virtual void changeScene();
- };
-private:
- void initArea();
- void enterArea();
- void doButtonPress(int indx);
-public:
- NamedHotspot _background;
- Keypad _keypad;
- SceneActor _southDoorway;
- SceneObject _northDoorway;
- Door _door;
- Scrolls _scrolls;
- SceneActor _containmentField;
- Gem _gem;
- SceneActor _cube;
- SceneActor _pulsingLights;
- Vampire _vampire;
- KeypadWindow _KeypadWindow;
- NorthExit _northExit;
- UpExit _upExit;
- EastExit _eastExit;
- DownExit _downExit;
- SouthExit _southExit;
- WestExit _westExit;
- ShaftExit _shaftExit;
- DoorExit _doorExit;
- SequenceManager _sequenceManager;
-
- bool _upExitStyle;
- bool _removeFlag;
- bool _vampireActive;
- Common::Point _vampireDestPos;
- int _vampireIndex;
-
- Scene1950();
- void synchronize(Serializer &s);
-
- virtual void postInit(SceneObjectList *OwnerList = NULL);
- virtual void remove();
- virtual void signal();
- virtual void process(Event &event);
-};
-
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_vampire.cpp b/engines/tsage/ringworld2/ringworld2_vampire.cpp
new file mode 100644
index 0000000000..9d3b7f91a5
--- /dev/null
+++ b/engines/tsage/ringworld2/ringworld2_vampire.cpp
@@ -0,0 +1,1821 @@
+/* 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 "tsage/ringworld2/ringworld2_vampire.h"
+
+namespace TsAGE {
+
+namespace Ringworld2 {
+
+/*--------------------------------------------------------------------------
+ * Scene 1950 - Flup Tube Corridor Maze
+ *
+ *--------------------------------------------------------------------------*/
+
+Scene1950::KeypadWindow::KeypadWindow() {
+ _buttonIndex = 0;
+}
+
+void Scene1950::KeypadWindow::synchronize(Serializer &s) {
+ SceneArea::synchronize(s);
+
+ s.syncAsSint16LE(_buttonIndex);
+}
+
+Scene1950::KeypadWindow::KeypadButton::KeypadButton() {
+ _buttonIndex = 0;
+ _pressed = false;
+ _toggled = false;
+}
+
+void Scene1950::KeypadWindow::KeypadButton::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_buttonIndex);
+ s.syncAsSint16LE(_pressed);
+ s.syncAsSint16LE(_toggled);
+}
+
+void Scene1950::KeypadWindow::KeypadButton::init(int indx) {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _buttonIndex = indx;
+ _pressed = false;
+ _toggled = false;
+
+ postInit();
+ setup(1971, 2, 1);
+ fixPriority(249);
+ setPosition(Common::Point(((_buttonIndex % 4) * 22) + 127, ((_buttonIndex / 4) * 19) + 71));
+ scene->_sceneAreas.push_front(this);
+}
+
+void Scene1950::KeypadWindow::KeypadButton::process(Event &event) {
+ if ((event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == CURSOR_USE)
+ && (_bounds.contains(event.mousePos)) && !_pressed) {
+ R2_GLOBALS._sound2.play(227);
+ if (!_toggled) {
+ setFrame(2);
+ _toggled = true;
+ } else {
+ setFrame(1);
+ _toggled = false;
+ }
+ _pressed = true;
+ event.handled = true;
+ }
+
+ if ((event.eventType == EVENT_BUTTON_UP) && _pressed) {
+ _pressed = false;
+ event.handled = true;
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+ scene->doButtonPress(_buttonIndex);
+ }
+}
+
+bool Scene1950::KeypadWindow::KeypadButton::startAction(CursorType action, Event &event) {
+ if (action == CURSOR_USE)
+ return false;
+ return SceneActor::startAction(action, event);
+}
+
+void Scene1950::KeypadWindow::remove() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+ for (_buttonIndex = 0; _buttonIndex < 16; ++_buttonIndex) {
+ scene->_sceneAreas.remove(&_buttons[_buttonIndex]);
+ _buttons[_buttonIndex].remove();
+ }
+
+ ModalWindow::remove();
+
+ if (!R2_GLOBALS.getFlag(37))
+ R2_GLOBALS._sound2.play(278);
+
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ scene->_eastExit._enabled = true;
+
+ if (!R2_GLOBALS.getFlag(37)) {
+ if (R2_GLOBALS.getFlag(36)) {
+ scene->_sceneMode = 1964;
+ scene->setAction(&scene->_sequenceManager, scene, 1964, &R2_GLOBALS._player, NULL);
+ } else {
+ scene->_sceneMode = 1965;
+ scene->setAction(&scene->_sequenceManager, scene, 1965, &R2_GLOBALS._player, NULL);
+ }
+ }
+}
+
+void Scene1950::KeypadWindow::setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ if (R2_GLOBALS._player._mover)
+ R2_GLOBALS._player.addMover(NULL);
+ R2_GLOBALS._player._canWalk = false;
+
+ ModalWindow::setup2(visage, stripFrameNum, frameNum, posX, posY);
+
+ _object1.fixPriority(248);
+ scene->_eastExit._enabled = false;
+ setup3(1950, 27, 28, 27);
+
+ for (_buttonIndex = 0; _buttonIndex < 16; _buttonIndex++)
+ _buttons[_buttonIndex].init(_buttonIndex);
+}
+
+void Scene1950::KeypadWindow::setup3(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
+ // Copy of Scene1200::LaserPanel::proc13()
+ _areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool Scene1950::Keypad::startAction(CursorType action, Event &event) {
+ if ((action != CURSOR_USE) || (R2_GLOBALS.getFlag(37)))
+ return SceneHotspot::startAction(action, event);
+
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_GLOBALS._player.disableControl();
+ if (R2_GLOBALS.getFlag(36)) {
+ scene->_sceneMode = 1962;
+ scene->setAction(&scene->_sequenceManager, scene, 1962, &R2_GLOBALS._player, NULL);
+ } else {
+ scene->_sceneMode = 1963;
+ scene->setAction(&scene->_sequenceManager, scene, 1963, &R2_GLOBALS._player, NULL);
+ }
+ return true;
+}
+
+bool Scene1950::Door::startAction(CursorType action, Event &event) {
+ if (action != R2_SCRITH_KEY)
+ return SceneActor::startAction(action, event);
+
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_GLOBALS._player.disableControl();
+ R2_INVENTORY.setObjectScene(R2_SCRITH_KEY, 0);
+ scene->_sceneMode = 1958;
+ scene->setAction(&scene->_sequenceManager, scene, 1958, &R2_GLOBALS._player, &scene->_door, NULL);
+ return true;
+}
+
+bool Scene1950::Scrolls::startAction(CursorType action, Event &event) {
+ if ((action != CURSOR_USE) || (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) != 1950))
+ return SceneActor::startAction(action, event);
+
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 1968;
+ scene->setAction(&scene->_sequenceManager, scene, 1968, &R2_GLOBALS._player, NULL);
+
+ return true;
+}
+
+bool Scene1950::Gem::startAction(CursorType action, Event &event) {
+ if ((action != CURSOR_USE) || (!R2_GLOBALS.getFlag(37)))
+ return SceneActor::startAction(action, event);
+
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 1967;
+ scene->setAction(&scene->_sequenceManager, scene, 1967, &R2_GLOBALS._player, NULL);
+
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene1950::Vampire::Vampire() {
+ _deadPosition = Common::Point(0, 0);
+ _deltaX = 0;
+ _deltaY = 0;
+ _vampireMode = 0;
+}
+
+void Scene1950::Vampire::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_deadPosition.x);
+ s.syncAsSint16LE(_deadPosition.y);
+ s.syncAsSint16LE(_deltaX);
+ s.syncAsSint16LE(_deltaY);
+ s.syncAsSint16LE(_vampireMode);
+}
+
+void Scene1950::Vampire::signal() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ switch (_vampireMode) {
+ case 19: {
+ _vampireMode = 0;
+ setVisage(1960);
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ setStrip(2);
+ else
+ setStrip(1);
+
+ NpcMover *mover = new NpcMover();
+ addMover(mover, &scene->_vampireDestPos, scene);
+ }
+ break;
+ case 20: {
+ // Non fatal shot
+ _vampireMode = 19;
+ R2_GLOBALS._player.setVisage(22);
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ R2_GLOBALS._player.setStrip(1);
+ else
+ R2_GLOBALS._player.setStrip(2);
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired--;
+
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ _deadPosition.x = _position.x + 10;
+ else
+ _deadPosition.x = _position.x - 10;
+ _deadPosition.y = _position.y - 4;
+
+ setVisage(1961);
+
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ setStrip(2);
+ else
+ setStrip(1);
+
+ animate(ANIM_MODE_2, NULL);
+ Common::Point pt = _deadPosition;
+ PlayerMover *mover = new PlayerMover();
+ addMover(mover, &pt, this);
+
+ R2_GLOBALS._player.enableControl();
+ }
+ break;
+ case 21: {
+ // Fatal shot
+ R2_GLOBALS._player.setVisage(22);
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ R2_GLOBALS._player.setStrip(1);
+ else
+ R2_GLOBALS._player.setStrip(2);
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+
+ setVisage(1961);
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ setStrip(4);
+ else
+ setStrip(3);
+ setDetails(1950, 15, -1, 17, 2, (SceneItem *) NULL);
+ addMover(NULL);
+ _numFrames = 8;
+ R2_GLOBALS._sound2.play(226);
+ animate(ANIM_MODE_5, NULL);
+ fixPriority(10);
+
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._isAlive = false;
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired--;
+ R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._position = _position;
+ _deltaX = (_position.x - R2_GLOBALS._player._position.x) / 2;
+ _deltaY = (_position.y - R2_GLOBALS._player._position.y) / 2;
+
+ byte vampireCount = 0;
+ for (byte i = 0; i < 18; ++i) {
+ if (!R2_GLOBALS._vampireData[i]._isAlive)
+ ++vampireCount;
+ }
+
+ if (vampireCount == 18) {
+ R2_GLOBALS.setFlag(36);
+ _vampireMode = 23;
+ Common::Point pt(R2_GLOBALS._player._position.x + _deltaX, R2_GLOBALS._player._position.y + _deltaY);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ } else if (vampireCount == 1) {
+ _vampireMode = 22;
+ Common::Point pt(R2_GLOBALS._player._position.x + _deltaX, R2_GLOBALS._player._position.y + _deltaY);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ } else {
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ }
+
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ scene->_eastExit._enabled = true;
+ else
+ scene->_westExit._enabled = true;
+
+ scene->_vampireActive = false;
+ }
+ break;
+ case 22:
+ SceneItem::display(1950, 18, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ break;
+ case 23:
+ SceneItem::display(1950, 25, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ scene->_sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ scene->setAction(&scene->_sequenceManager, scene, 1960, &R2_GLOBALS._player, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+bool Scene1950::Vampire::startAction(CursorType action, Event &event) {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ if (!R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._isAlive ||
+ (action != R2_PHOTON_STUNNER))
+ return SceneActor::startAction(action, event);
+
+ R2_GLOBALS._player.disableControl();
+
+ if (R2_GLOBALS._vampireData[scene->_vampireIndex - 1]._shotsRequired <= 1)
+ _vampireMode = 21;
+ else
+ _vampireMode = 20;
+
+ R2_GLOBALS._player.setVisage(25);
+ if (R2_GLOBALS._flubMazeEntryDirection == 3)
+ R2_GLOBALS._player.setStrip(2);
+ else
+ R2_GLOBALS._player.setStrip(1);
+ R2_GLOBALS._player.animate(ANIM_MODE_5, this);
+ R2_GLOBALS._sound3.play(99);
+
+ return true;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void Scene1950::NorthExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 1;
+ scene->_sceneMode = 11;
+
+ Common::Point pt(160, 127);
+ PlayerMover *mover = new PlayerMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+}
+
+void Scene1950::UpExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 2;
+ scene->_sceneMode = 12;
+
+ if (!scene->_upExitStyle) {
+ if (R2_GLOBALS.getFlag(36))
+ scene->setAction(&scene->_sequenceManager, scene, 1953, &R2_GLOBALS._player, NULL);
+ else
+ scene->setAction(&scene->_sequenceManager, scene, 1970, &R2_GLOBALS._player, NULL);
+ } else {
+ if (R2_GLOBALS.getFlag(36))
+ scene->setAction(&scene->_sequenceManager, scene, 1952, &R2_GLOBALS._player, NULL);
+ else
+ scene->setAction(&scene->_sequenceManager, scene, 1969, &R2_GLOBALS._player, NULL);
+ }
+}
+
+void Scene1950::EastExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 3;
+ scene->_sceneMode = 13;
+
+ if (scene->_vampireActive)
+ R2_GLOBALS._player.animate(ANIM_MODE_9);
+
+ Common::Point pt(340, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+}
+
+void Scene1950::DownExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 4;
+ scene->_sceneMode = 14;
+
+ if (R2_GLOBALS.getFlag(36))
+ scene->setAction(&scene->_sequenceManager, scene, 1956, &R2_GLOBALS._player, NULL);
+ else
+ scene->setAction(&scene->_sequenceManager, scene, 1973, &R2_GLOBALS._player, NULL);
+}
+
+void Scene1950::SouthExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 5;
+ scene->_sceneMode = 15;
+
+ Common::Point pt(160, 213);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+}
+
+void Scene1950::WestExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 6;
+
+ if (R2_GLOBALS._flubMazeArea == 2) {
+ // In the very first corridor area after the Scrith Door
+ if ((R2_GLOBALS.getFlag(36)) && (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 2) && (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2)) {
+ scene->_sceneMode = 1961;
+ Common::Point pt(-20, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+ } else {
+ if (!R2_GLOBALS.getFlag(36))
+ SceneItem::display(1950, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ if ((R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950) || (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 1950))
+ SceneItem::display(1950, 34, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ scene->_sceneMode = 0;
+ Common::Point pt(30, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+ }
+ } else {
+ if (scene->_vampireActive)
+ R2_GLOBALS._player.animate(ANIM_MODE_9);
+
+ scene->_sceneMode = 16;
+ Common::Point pt(-20, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+ }
+}
+
+void Scene1950::ShaftExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 0;
+ scene->_sceneMode = 1951;
+ scene->setAction(&scene->_sequenceManager, scene, 1951, &R2_GLOBALS._player, NULL);
+}
+
+void Scene1950::DoorExit::changeScene() {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._flubMazeEntryDirection = 3;
+ if (R2_GLOBALS._player._visage == 22) {
+ scene->_sceneMode = 1975;
+ scene->setAction(&scene->_sequenceManager, scene, 1975, &R2_GLOBALS._player, NULL);
+ } else {
+ SceneItem::display(1950, 22, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ R2_GLOBALS._flubMazeEntryDirection = 0;
+ scene->_sceneMode = 0;
+ Common::Point pt(250, 150);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+ _enabled = true;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene1950::Scene1950() {
+ _upExitStyle = false;
+ _removeFlag = false;
+ _vampireActive = false;
+ _vampireDestPos = Common::Point(0, 0);
+ _vampireIndex = 0;
+}
+
+void Scene1950::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_upExitStyle);
+ s.syncAsSint16LE(_removeFlag);
+ s.syncAsSint16LE(_vampireActive);
+ s.syncAsSint16LE(_vampireDestPos.x);
+ s.syncAsSint16LE(_vampireDestPos.y);
+ s.syncAsSint16LE(_vampireIndex);
+}
+
+void Scene1950::initArea() {
+ _northExit._enabled = false;
+ _upExit._enabled = false;
+ _eastExit._enabled = false;
+ _downExit._enabled = false;
+ _southExit._enabled = false;
+ _westExit._enabled = false;
+ _shaftExit._enabled = false;
+ _doorExit._enabled = false;
+ _northExit._insideArea = false;
+ _upExit._insideArea = false;
+ _eastExit._insideArea = false;
+ _downExit._insideArea = false;
+ _southExit._insideArea = false;
+ _westExit._insideArea = false;
+ _shaftExit._insideArea = false;
+ _doorExit._insideArea = false;
+ _northExit._moving = false;
+ _upExit._moving = false;
+ _eastExit._moving = false;
+ _downExit._moving = false;
+ _southExit._moving = false;
+ _westExit._moving = false;
+ _shaftExit._moving = false;
+ _doorExit._moving = false;
+ _upExitStyle = false;
+
+ switch (R2_GLOBALS._flubMazeArea - 1) {
+ case 0:
+ loadScene(1948);
+ break;
+ case 1:
+ // No break on purpose
+ case 8:
+ // No break on purpose
+ case 10:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 23:
+ // No break on purpose
+ case 30:
+ // No break on purpose
+ case 44:
+ // No break on purpose
+ case 72:
+ // No break on purpose
+ case 74:
+ // No break on purpose
+ case 86:
+ // No break on purpose
+ case 96:
+ // No break on purpose
+ case 103:
+ loadScene(1950);
+ break;
+ case 2:
+ // No break on purpose
+ case 29:
+ loadScene(1965);
+ break;
+ case 3:
+ // No break on purpose
+ case 9:
+ // No break on purpose
+ case 11:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 24:
+ // No break on purpose
+ case 39:
+ // No break on purpose
+ case 45:
+ // No break on purpose
+ case 71:
+ // No break on purpose
+ case 73:
+ // No break on purpose
+ case 75:
+ // No break on purpose
+ case 79:
+ // No break on purpose
+ case 85:
+ // No break on purpose
+ case 87:
+ // No break on purpose
+ case 95:
+ loadScene(1955);
+ break;
+ case 4:
+ // No break on purpose
+ case 6:
+ // No break on purpose
+ case 13:
+ // No break on purpose
+ case 27:
+ // No break on purpose
+ case 41:
+ // No break on purpose
+ case 48:
+ // No break on purpose
+ case 50:
+ // No break on purpose
+ case 54:
+ // No break on purpose
+ case 76:
+ // No break on purpose
+ case 80:
+ // No break on purpose
+ case 90:
+ // No break on purpose
+ case 104:
+ loadScene(1975);
+ break;
+ case 5:
+ // No break on purpose
+ case 7:
+ // No break on purpose
+ case 14:
+ // No break on purpose
+ case 28:
+ // No break on purpose
+ case 32:
+ // No break on purpose
+ case 47:
+ // No break on purpose
+ case 53:
+ loadScene(1997);
+ break;
+ case 17:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 25:
+ // No break on purpose
+ case 31:
+ // No break on purpose
+ case 33:
+ // No break on purpose
+ case 46:
+ loadScene(1995);
+ break;
+ case 18:
+ // No break on purpose
+ case 22:
+ // No break on purpose
+ case 26:
+ // No break on purpose
+ case 36:
+ // No break on purpose
+ case 38:
+ // No break on purpose
+ case 43:
+ // No break on purpose
+ case 51:
+ // No break on purpose
+ case 70:
+ // No break on purpose
+ case 78:
+ // No break on purpose
+ case 84:
+ // No break on purpose
+ case 89:
+ // No break on purpose
+ case 101:
+ loadScene(1970);
+ break;
+ case 21:
+ // No break on purpose
+ case 34:
+ // No break on purpose
+ case 57:
+ // No break on purpose
+ case 58:
+ // No break on purpose
+ case 59:
+ // No break on purpose
+ case 62:
+ // No break on purpose
+ case 65:
+ loadScene(1980);
+ break;
+ case 35:
+ // No break on purpose
+ case 61:
+ // No break on purpose
+ case 77:
+ // No break on purpose
+ case 83:
+ loadScene(1982);
+ break;
+ case 37:
+ // No break on purpose
+ case 52:
+ // No break on purpose
+ case 82:
+ // No break on purpose
+ case 88:
+ // No break on purpose
+ case 92:
+ // No break on purpose
+ case 97:
+ // No break on purpose
+ case 100:
+ loadScene(1962);
+ break;
+ case 40:
+ // No break on purpose
+ case 102:
+ loadScene(1960);
+ break;
+ case 42:
+ // No break on purpose
+ case 55:
+ // No break on purpose
+ case 60:
+ // No break on purpose
+ case 66:
+ // No break on purpose
+ case 68:
+ // No break on purpose
+ case 69:
+ // No break on purpose
+ case 93:
+ // No break on purpose
+ case 98:
+ loadScene(1990);
+ break;
+ case 49:
+ // No break on purpose
+ case 81:
+ // No break on purpose
+ case 91:
+ // No break on purpose
+ case 94:
+ // No break on purpose
+ case 99:
+ loadScene(1967);
+ break;
+ case 56:
+ // No break on purpose
+ case 63:
+ // No break on purpose
+ case 64:
+ // No break on purpose
+ case 67:
+ loadScene(1985);
+ _upExitStyle = true;
+ break;
+ default:
+ break;
+ }
+
+ if (R2_GLOBALS._flubMazeArea != 1)
+ R2_GLOBALS._walkRegions.load(1950);
+
+ switch (R2_GLOBALS._flubMazeArea - 1) {
+ case 0:
+ _shaftExit._enabled = true;
+ if ((R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0) && (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950))
+ _doorExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(2);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ break;
+ case 1:
+ // No break on purpose
+ case 2:
+ // No break on purpose
+ case 3:
+ // No break on purpose
+ case 8:
+ // No break on purpose
+ case 9:
+ // No break on purpose
+ case 10:
+ // No break on purpose
+ case 11:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 23:
+ // No break on purpose
+ case 24:
+ // No break on purpose
+ case 29:
+ // No break on purpose
+ case 30:
+ // No break on purpose
+ case 39:
+ // No break on purpose
+ case 40:
+ // No break on purpose
+ case 44:
+ // No break on purpose
+ case 45:
+ // No break on purpose
+ case 71:
+ // No break on purpose
+ case 72:
+ // No break on purpose
+ case 73:
+ // No break on purpose
+ case 74:
+ // No break on purpose
+ case 75:
+ // No break on purpose
+ case 79:
+ // No break on purpose
+ case 85:
+ // No break on purpose
+ case 86:
+ // No break on purpose
+ case 87:
+ // No break on purpose
+ case 95:
+ // No break on purpose
+ case 96:
+ // No break on purpose
+ case 102:
+ // No break on purpose
+ case 103:
+ _eastExit._enabled = true;
+ _westExit._enabled = true;
+ break;
+ case 4:
+ // No break on purpose
+ case 6:
+ // No break on purpose
+ case 13:
+ // No break on purpose
+ case 17:
+ // No break on purpose
+ case 20:
+ // No break on purpose
+ case 25:
+ // No break on purpose
+ case 27:
+ // No break on purpose
+ case 31:
+ // No break on purpose
+ case 33:
+ // No break on purpose
+ case 37:
+ // No break on purpose
+ case 41:
+ // No break on purpose
+ case 46:
+ // No break on purpose
+ case 48:
+ // No break on purpose
+ case 50:
+ // No break on purpose
+ case 52:
+ // No break on purpose
+ case 54:
+ // No break on purpose
+ case 76:
+ // No break on purpose
+ case 80:
+ // No break on purpose
+ case 82:
+ // No break on purpose
+ case 88:
+ // No break on purpose
+ case 90:
+ // No break on purpose
+ case 92:
+ // No break on purpose
+ case 97:
+ // No break on purpose
+ case 100:
+ // No break on purpose
+ case 104:
+ _westExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ break;
+ case 5:
+ // No break on purpose
+ case 7:
+ // No break on purpose
+ case 14:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 22:
+ // No break on purpose
+ case 26:
+ // No break on purpose
+ case 28:
+ // No break on purpose
+ case 32:
+ // No break on purpose
+ case 36:
+ // No break on purpose
+ case 38:
+ // No break on purpose
+ case 43:
+ // No break on purpose
+ case 47:
+ // No break on purpose
+ case 49:
+ // No break on purpose
+ case 51:
+ // No break on purpose
+ case 53:
+ // No break on purpose
+ case 70:
+ // No break on purpose
+ case 78:
+ // No break on purpose
+ case 81:
+ // No break on purpose
+ case 84:
+ // No break on purpose
+ case 89:
+ // No break on purpose
+ case 91:
+ // No break on purpose
+ case 94:
+ // No break on purpose
+ case 99:
+ // No break on purpose
+ case 101:
+ _eastExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(13);
+ break;
+ default:
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+ R2_GLOBALS._walkRegions.disableRegion(9);
+ R2_GLOBALS._walkRegions.disableRegion(13);
+ break;
+ }
+
+ _northDoorway.remove();
+ _northDoorway.removeObject();
+ _southDoorway.remove();
+
+ switch (R2_GLOBALS._flubMazeArea - 4) {
+ case 0:
+ // No break on purpose
+ case 3:
+ // No break on purpose
+ case 16:
+ // No break on purpose
+ case 22:
+ // No break on purpose
+ case 24:
+ // No break on purpose
+ case 32:
+ // No break on purpose
+ case 33:
+ // No break on purpose
+ case 45:
+ // No break on purpose
+ case 46:
+ // No break on purpose
+ case 48:
+ // No break on purpose
+ case 51:
+ // No break on purpose
+ case 56:
+ // No break on purpose
+ case 59:
+ // No break on purpose
+ case 67:
+ // No break on purpose
+ case 68:
+ // No break on purpose
+ case 70:
+ // No break on purpose
+ case 73:
+ // No break on purpose
+ case 82:
+ // No break on purpose
+ case 90:
+ _northExit._enabled = true;
+ _northDoorway.setup(1950, (R2_GLOBALS._flubMazeArea % 2) + 1, 1, 160, 137, 25);
+ //visage,strip,frame,px,py,priority,effect
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
+ _southDoorway.setFrame(2);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ break;
+ case 7:
+ // No break on purpose
+ case 10:
+ // No break on purpose
+ case 23:
+ // No break on purpose
+ case 29:
+ // No break on purpose
+ case 31:
+ // No break on purpose
+ case 39:
+ // No break on purpose
+ case 40:
+ // No break on purpose
+ case 52:
+ // No break on purpose
+ case 53:
+ // No break on purpose
+ case 55:
+ // No break on purpose
+ case 63:
+ // No break on purpose
+ case 65:
+ // No break on purpose
+ case 66:
+ // No break on purpose
+ case 75:
+ // No break on purpose
+ case 77:
+ // No break on purpose
+ case 81:
+ // No break on purpose
+ case 87:
+ // No break on purpose
+ case 89:
+ // No break on purpose
+ case 97:
+ _southExit._enabled = true;
+
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
+ _southDoorway.setFrame(3);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
+ break;
+ case 58:
+ // No break on purpose
+ case 74:
+ // No break on purpose
+ case 80:
+ _northExit._enabled = true;
+ _southExit._enabled = true;
+
+ _northDoorway.setup(1950, (R2_GLOBALS._flubMazeArea % 2) + 1, 1, 160, 137, 25);
+
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip((((R2_GLOBALS._flubMazeArea - 1) / 35) % 2) + 1);
+ _southDoorway.setFrame(3);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
+ R2_GLOBALS._walkRegions.disableRegion(3);
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ break;
+ default:
+ _southDoorway.postInit();
+ _southDoorway.setVisage(1950);
+ _southDoorway.setStrip(((R2_GLOBALS._flubMazeArea - 1) / 35) % 2 + 1);
+ _southDoorway.setFrame(2);
+ _southDoorway.setPosition(Common::Point(160, 167));
+ _southDoorway.fixPriority(220);
+ break;
+ }
+
+ switch (R2_GLOBALS._flubMazeArea - 3) {
+ case 0:
+ // No break on purpose
+ case 3:
+ // No break on purpose
+ case 5:
+ // No break on purpose
+ case 12:
+ // No break on purpose
+ case 15:
+ // No break on purpose
+ case 18:
+ // No break on purpose
+ case 19:
+ // No break on purpose
+ case 23:
+ // No break on purpose
+ case 26:
+ // No break on purpose
+ case 27:
+ // No break on purpose
+ case 29:
+ // No break on purpose
+ case 30:
+ // No break on purpose
+ case 31:
+ // No break on purpose
+ case 32:
+ // No break on purpose
+ case 44:
+ // No break on purpose
+ case 45:
+ // No break on purpose
+ case 51:
+ // No break on purpose
+ case 55:
+ // No break on purpose
+ case 56:
+ // No break on purpose
+ case 57:
+ // No break on purpose
+ case 60:
+ // No break on purpose
+ case 63:
+ _upExit._enabled = true;
+ break;
+ case 54:
+ // No break on purpose
+ case 61:
+ // No break on purpose
+ case 62:
+ // No break on purpose
+ case 65:
+ _upExit._enabled = true;
+ // No break on purpose
+ case 35:
+ // No break on purpose
+ case 38:
+ // No break on purpose
+ case 40:
+ // No break on purpose
+ case 47:
+ // No break on purpose
+ case 50:
+ // No break on purpose
+ case 53:
+ // No break on purpose
+ case 58:
+ // No break on purpose
+ case 64:
+ // No break on purpose
+ case 66:
+ // No break on purpose
+ case 67:
+ // No break on purpose
+ case 79:
+ // No break on purpose
+ case 80:
+ // No break on purpose
+ case 86:
+ // No break on purpose
+ case 89:
+ // No break on purpose
+ case 90:
+ // No break on purpose
+ case 91:
+ // No break on purpose
+ case 92:
+ // No break on purpose
+ case 95:
+ // No break on purpose
+ case 96:
+ // No break on purpose
+ case 97:
+ // No break on purpose
+ case 98:
+ // No break on purpose
+ case 100:
+ _downExit._enabled = true;
+ R2_GLOBALS._walkRegions.disableRegion(4);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(10);
+ R2_GLOBALS._walkRegions.disableRegion(11);
+ default:
+ break;
+ }
+ R2_GLOBALS._uiElements.draw();
+}
+
+void Scene1950::enterArea() {
+ R2_GLOBALS._player.disableControl();
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+
+ _vampire.remove();
+ _door.remove();
+ _scrolls.remove();
+
+ _vampireActive = false;
+ _vampireIndex = 0;
+
+ // Certain areas have a vampire in them
+ switch (R2_GLOBALS._flubMazeArea) {
+ case 10:
+ _vampireIndex = 1;
+ break;
+ case 13:
+ _vampireIndex = 2;
+ break;
+ case 16:
+ _vampireIndex = 3;
+ break;
+ case 17:
+ _vampireIndex = 4;
+ break;
+ case 24:
+ _vampireIndex = 5;
+ break;
+ case 25:
+ _vampireIndex = 6;
+ break;
+ case 31:
+ _vampireIndex = 7;
+ break;
+ case 40:
+ _vampireIndex = 8;
+ break;
+ case 45:
+ _vampireIndex = 9;
+ break;
+ case 46:
+ _vampireIndex = 10;
+ break;
+ case 73:
+ _vampireIndex = 11;
+ break;
+ case 75:
+ _vampireIndex = 12;
+ break;
+ case 80:
+ _vampireIndex = 13;
+ break;
+ case 87:
+ _vampireIndex = 14;
+ break;
+ case 88:
+ _vampireIndex = 15;
+ break;
+ case 96:
+ _vampireIndex = 16;
+ break;
+ case 97:
+ _vampireIndex = 17;
+ break;
+ case 104:
+ _vampireIndex = 18;
+ break;
+ default:
+ break;
+ }
+
+ if (_vampireIndex != 0) {
+ _vampire.postInit();
+ _vampire._numFrames = 6;
+ _vampire._moveRate = 6;
+ _vampire._moveDiff = Common::Point(3, 2);
+ _vampire._effect = EFFECT_SHADED;
+
+ if (!R2_GLOBALS._vampireData[_vampireIndex - 1]._isAlive) {
+ // Show vampire ashes
+ _vampire.setPosition(Common::Point(R2_GLOBALS._vampireData[_vampireIndex - 1]._position));
+ _vampire.animate(ANIM_MODE_NONE, NULL);
+ _vampire.addMover(NULL);
+ _vampire.setVisage(1961);
+ _vampire.setStrip(4);
+ _vampire.setFrame(10);
+ _vampire.fixPriority(10);
+ _vampire.setDetails(1950, 15, -1, 17, 2, (SceneItem *) NULL);
+ } else {
+ // Start the vampire
+ _vampire.setVisage(1960);
+ _vampire.setPosition(Common::Point(160, 130));
+ _vampire.animate(ANIM_MODE_2, NULL);
+ _vampire.setDetails(1950, 12, -1, 14, 2, (SceneItem *) NULL);
+ _vampireActive = true;
+ }
+ }
+ if ((R2_GLOBALS._flubMazeArea == 1) && (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) != 0)) {
+ // Show doorway at the right hand side of the very first flub corridor
+ _door.postInit();
+ _door.setVisage(1948);
+ _door.setStrip(3);
+ _door.setPosition(Common::Point(278, 155));
+ _door.fixPriority(100);
+ _door.setDetails(1950, 19, 20, 23, 2, (SceneItem *) NULL);
+ }
+
+ if (R2_GLOBALS._flubMazeArea == 102) {
+ R2_GLOBALS._walkRegions.load(1951);
+ R2_GLOBALS._walkRegions.disableRegion(1);
+ R2_GLOBALS._walkRegions.disableRegion(5);
+ R2_GLOBALS._walkRegions.disableRegion(6);
+ R2_GLOBALS._walkRegions.disableRegion(7);
+
+ _cube.postInit();
+ _cube.setVisage(1970);
+ _cube.setStrip(1);
+ if (R2_GLOBALS.getFlag(37))
+ _cube.setFrame(3);
+ else
+ _cube.setFrame(1);
+ _cube.setPosition(Common::Point(193, 158));
+ _cube.setDetails(1950, 3, 4, 5, 2, (SceneItem *) NULL);
+
+ _pulsingLights.postInit();
+ _pulsingLights.setVisage(1970);
+ _pulsingLights.setStrip(3);
+ _pulsingLights.animate(ANIM_MODE_2, NULL);
+ _pulsingLights._numFrames = 6;
+ _pulsingLights.setPosition(Common::Point(194, 158));
+ _pulsingLights.fixPriority(159);
+
+ _keypad.setDetails(Rect(188, 124, 199, 133), 1950, 27, 28, -1, 2, NULL);
+
+ if (R2_INVENTORY.getObjectScene(R2_SAPPHIRE_BLUE) == 1950) {
+ _gem.postInit();
+ _gem.setVisage(1970);
+ _gem.setStrip(1);
+ _gem.setFrame(2);
+ _gem.fixPriority(160);
+ }
+
+ if (R2_GLOBALS.getFlag(37)) {
+ _gem.setPosition(Common::Point(192, 118));
+ _gem.setDetails(1950, 9, 4, -1, 2, (SceneItem *) NULL);
+ } else {
+ _containmentField.postInit();
+ _containmentField.setVisage(1970);
+ _containmentField.setStrip(4);
+ _containmentField._numFrames = 4;
+ _containmentField.animate(ANIM_MODE_8, 0, NULL);
+ _containmentField.setPosition(Common::Point(192, 121));
+ _containmentField.fixPriority(159);
+ _containmentField.setDetails(1950, 6, 7, 8, 2, (SceneItem *) NULL);
+
+ _gem.setPosition(Common::Point(192, 109));
+ _gem.setDetails(1950, 9, 7, 8, 2, (SceneItem *) NULL);
+ }
+
+ _scrolls.postInit();
+ _scrolls.setVisage(1972);
+ _scrolls.setStrip(1);
+ _scrolls.setPosition(Common::Point(76, 94));
+ _scrolls.fixPriority(25);
+ _scrolls.setDetails(1950, 30, -1, -1, 2, (SceneItem *) NULL);
+ if (R2_INVENTORY.getObjectScene(R2_ANCIENT_SCROLLS) == 2)
+ _scrolls.setFrame(2);
+ else
+ _scrolls.setFrame(1);
+
+ _removeFlag = true;
+ } else if (_removeFlag) {
+ _cube.remove();
+ _containmentField.remove();
+ _gem.remove();
+ _pulsingLights.remove();
+ _scrolls.remove();
+
+ R2_GLOBALS._sceneItems.remove(&_background);
+ _background.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 2, NULL);
+
+ _removeFlag = false;
+ }
+
+ switch (R2_GLOBALS._flubMazeEntryDirection) {
+ case 0:
+ _sceneMode = 1950;
+ if (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0)
+ // The original uses CURSOR_ARROW. CURSOR_WALK is much more coherent
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ else
+ setAction(&_sequenceManager, this, 1950, &R2_GLOBALS._player, NULL);
+
+ break;
+ case 1: {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ R2_GLOBALS._player.setPosition(Common::Point(160, 213));
+ Common::Point pt(160, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ }
+ break;
+ case 2:
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ if (R2_GLOBALS.getFlag(36))
+ setAction(&_sequenceManager, this, 1957, &R2_GLOBALS._player, NULL);
+ else
+ setAction(&_sequenceManager, this, 1974, &R2_GLOBALS._player, NULL);
+ break;
+ case 3:
+ // Entering from the left
+ if (!_vampireActive) {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ R2_GLOBALS._player.setPosition(Common::Point(-20, 160));
+ Common::Point pt(30, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ } else {
+ _sceneMode = 18;
+ _eastExit._enabled = false;
+ _vampireDestPos = Common::Point(60, 152);
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ R2_GLOBALS._player._canWalk = false;
+
+ _vampire.setStrip(2);
+ NpcMover *mover = new NpcMover();
+ _vampire.addMover(mover, &_vampireDestPos, this);
+
+ R2_GLOBALS._player.setPosition(Common::Point(-20, 160));
+ Common::Point pt2(30, 160);
+ NpcMover *mover2 = new NpcMover();
+ R2_GLOBALS._player.addMover(mover2, &pt2, NULL);
+ }
+ break;
+ case 4:
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ if (!_upExitStyle) {
+ if (R2_GLOBALS.getFlag(36))
+ setAction(&_sequenceManager, this, 1955, &R2_GLOBALS._player, NULL);
+ else
+ setAction(&_sequenceManager, this, 1972, &R2_GLOBALS._player, NULL);
+ } else {
+ if (R2_GLOBALS.getFlag(36))
+ setAction(&_sequenceManager, this, 1954, &R2_GLOBALS._player, NULL);
+ else
+ setAction(&_sequenceManager, this, 1971, &R2_GLOBALS._player, NULL);
+ }
+ break;
+ case 5: {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ R2_GLOBALS._player.setPosition(Common::Point(160, 127));
+ Common::Point pt(160, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ }
+ break;
+ case 6:
+ // Entering from the right
+ if (!_vampireActive) {
+ _sceneMode = R2_GLOBALS._flubMazeEntryDirection;
+ if (R2_GLOBALS._flubMazeArea == 1) {
+ setAction(&_sequenceManager, this, 1961, &R2_GLOBALS._player, NULL);
+ } else {
+ R2_GLOBALS._player.setPosition(Common::Point(340, 160));
+ Common::Point pt(289, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ }
+ } else {
+ _sceneMode = 17;
+ _westExit._enabled = false;
+ _vampireDestPos = Common::Point(259, 152);
+
+ R2_GLOBALS._player.enableControl(CURSOR_USE);
+ R2_GLOBALS._player._canWalk = false;
+
+ _vampire.setStrip(1);
+ NpcMover *mover = new NpcMover();
+ _vampire.addMover(mover, &_vampireDestPos, this);
+
+ R2_GLOBALS._player.setPosition(Common::Point(340, 160));
+ Common::Point pt2(289, 160);
+ NpcMover *mover2 = new NpcMover();
+ R2_GLOBALS._player.addMover(mover2, &pt2, NULL);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Scene1950::doButtonPress(int indx) {
+ Scene1950 *scene = (Scene1950 *)R2_GLOBALS._sceneManager._scene;
+ R2_GLOBALS._player.disableControl();
+
+ int prevIndex = indx - 1;
+ if ((indx / 4) == (prevIndex / 4)) {
+ if (prevIndex < 0)
+ prevIndex = 3;
+ } else {
+ prevIndex += 4;
+ }
+
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
+ } else {
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
+ }
+
+ prevIndex = indx + 1;
+ if ((indx / 4) == (prevIndex / 4)) {
+ if (prevIndex > 15)
+ prevIndex = 12;
+ } else {
+ prevIndex -= 4;
+ }
+
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
+ } else {
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
+ }
+
+ prevIndex = indx - 4;
+ if (prevIndex < 0)
+ prevIndex += 16;
+
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
+ } else {
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
+ }
+
+ prevIndex = indx + 4;
+ if (prevIndex > 15)
+ prevIndex -= 16;
+
+ assert(prevIndex >= 0 && prevIndex < 16);
+ if (!_KeypadWindow._buttons[prevIndex]._toggled) {
+ _KeypadWindow._buttons[prevIndex].setFrame(2);
+ _KeypadWindow._buttons[prevIndex]._toggled = true;
+ } else {
+ _KeypadWindow._buttons[prevIndex].setFrame(1);
+ _KeypadWindow._buttons[prevIndex]._toggled = false;
+ }
+
+ // Check whether all the buttons are highlighted
+ int cpt = 0;
+ for (prevIndex = 0; prevIndex < 16; prevIndex++) {
+ if (_KeypadWindow._buttons[prevIndex]._toggled)
+ ++cpt;
+ }
+
+ if (cpt != 16) {
+ R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._player._canWalk = false;
+ } else {
+ R2_GLOBALS.setFlag(37);
+ _sceneMode = 24;
+ setAction(&_sequenceManager, scene, 1976, NULL);
+ }
+}
+
+void Scene1950::postInit(SceneObjectList *OwnerList) {
+ _upExitStyle = false;
+ _removeFlag = false;
+ _vampireActive = false;
+ _vampireIndex = 0;
+ if (R2_GLOBALS._sceneManager._previousScene == 300)
+ R2_GLOBALS._flubMazeArea = 103;
+
+ initArea();
+ SceneExt::postInit();
+ R2_GLOBALS._sound1.play(105);
+
+ _northExit.setDetails(Rect(130, 46, 189, 135), SHADECURSOR_UP, 1950);
+ _northExit.setDest(Common::Point(160, 145));
+
+ _upExit.setDetails(Rect(208, 0, 255, 73), EXITCURSOR_N, 1950);
+ _upExit.setDest(Common::Point(200, 151));
+
+ _eastExit.setDetails(Rect(305, 95, 320, 147), EXITCURSOR_E, 1950);
+ _eastExit.setDest(Common::Point(312, 160));
+
+ _downExit.setDetails(Rect(208, 99, 255, 143), EXITCURSOR_S, 1950);
+ _downExit.setDest(Common::Point(200, 151));
+
+ _southExit.setDetails(Rect(113, 154, 206, 168), SHADECURSOR_DOWN, 1950);
+ _southExit.setDest(Common::Point(160, 165));
+
+ _westExit.setDetails(Rect(0, 95, 14, 147), EXITCURSOR_W, 1950);
+ _westExit.setDest(Common::Point(7, 160));
+
+ _shaftExit.setDetails(Rect(72, 54, 120, 128), EXITCURSOR_NW, 1950);
+ _shaftExit.setDest(Common::Point(120, 140));
+
+ _doorExit.setDetails(Rect(258, 60, 300, 145), EXITCURSOR_NE, 1950);
+ _doorExit.setDest(Common::Point(268, 149));
+
+ R2_GLOBALS._player.postInit();
+ if ( (R2_INVENTORY.getObjectScene(R2_TANNER_MASK) == 0) && (R2_INVENTORY.getObjectScene(R2_PURE_GRAIN_ALCOHOL) == 0)
+ && (R2_INVENTORY.getObjectScene(R2_SOAKED_FACEMASK) == 0) && (!R2_GLOBALS.getFlag(36)) )
+ R2_GLOBALS._player.setVisage(22);
+ else
+ R2_GLOBALS._player.setVisage(20);
+
+ R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
+ _background.setDetails(Rect(0, 0, 320, 200), 1950, 0, 1, 2, 1, NULL);
+
+ enterArea();
+}
+
+void Scene1950::remove() {
+ R2_GLOBALS._sound1.stop();
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ SceneExt::remove();
+}
+
+void Scene1950::signal() {
+ switch (_sceneMode) {
+ case 11:
+ R2_GLOBALS._flubMazeArea += 7;
+ initArea();
+ enterArea();
+ break;
+ case 12:
+ // Moving up a ladder within the Flub maze
+ R2_GLOBALS._flubMazeArea += 35;
+ initArea();
+ enterArea();
+ break;
+ case 1975:
+ SceneItem::display(1950, 21, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, 1,
+ SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
+ // No break on purpose
+ case 13:
+ // Moving east within the Flub maze
+ ++R2_GLOBALS._flubMazeArea;
+ initArea();
+ enterArea();
+ break;
+ case 14:
+ // Moving down a ladder within the Flub maze
+ R2_GLOBALS._flubMazeArea -= 35;
+ initArea();
+ enterArea();
+ break;
+ case 15:
+ R2_GLOBALS._flubMazeArea -= 7;
+ initArea();
+ enterArea();
+ break;
+ case 16:
+ // Moving west within the Flub maze
+ // No break on purpose
+ case 1961:
+ --R2_GLOBALS._flubMazeArea;
+ initArea();
+ enterArea();
+ break;
+ case 17: {
+ _sceneMode = 13;
+ R2_GLOBALS._flubMazeEntryDirection = 3;
+ _vampireActive = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._player._canWalk = true;
+ R2_GLOBALS._player.setVisage(22);
+ R2_GLOBALS._player.animate(ANIM_MODE_9);
+ Common::Point pt(340, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ Common::Point pt2(289, 160);
+ NpcMover *mover2 = new NpcMover();
+ _vampire.addMover(mover2, &pt2, NULL);
+ }
+ break;
+ case 18: {
+ _sceneMode = 16;
+ R2_GLOBALS._flubMazeEntryDirection = 6;
+ _vampireActive = false;
+ R2_GLOBALS._player.disableControl(CURSOR_WALK);
+ R2_GLOBALS._player._canWalk = true;
+ R2_GLOBALS._player.setVisage(22);
+ R2_GLOBALS._player.animate(ANIM_MODE_9);
+ Common::Point pt(-20, 160);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ Common::Point pt2(30, 160);
+ NpcMover *mover2 = new NpcMover();
+ _vampire.addMover(mover2, &pt2, NULL);
+ }
+ break;
+ case 24:
+ _KeypadWindow.remove();
+ _sceneMode = 1966;
+ _cube.setFrame(3);
+ setAction(&_sequenceManager, this, 1966, &_containmentField, &_gem, NULL);
+ break;
+ case 1951:
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sceneManager.changeScene(1945);
+ break;
+ case 1958:
+ SceneItem::display(1950, 24, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ _doorExit._enabled = true;
+ break;
+ case 1959:
+ R2_INVENTORY.setObjectScene(R2_SOAKED_FACEMASK, 0);
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ _doorExit._enabled = true;
+ break;
+ case 1962:
+ // No break on purpose
+ case 1963:
+ R2_GLOBALS._player.enableControl();
+ _KeypadWindow.setup2(1971, 1, 1, 160, 135);
+ break;
+ case 1964:
+ // No break on purpose
+ case 1965:
+ if (!R2_GLOBALS.getFlag(37))
+ SceneItem::display(1950, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, LIST_END);
+
+ R2_GLOBALS._player.enableControl();
+ break;
+ case 1966:
+ _containmentField.remove();
+ if (R2_GLOBALS.getFlag(36)) {
+ _sceneMode = 1964;
+ setAction(&_sequenceManager, this, 1964, &R2_GLOBALS._player, NULL);
+ } else {
+ _sceneMode = 1965;
+ setAction(&_sequenceManager, this, 1965, &R2_GLOBALS._player, NULL);
+ }
+ _gem.setDetails(1950, 9, -1, -1, 2, (SceneItem *) NULL);
+ break;
+ case 1967: {
+ _sceneMode = 0;
+ R2_INVENTORY.setObjectScene(R2_SAPPHIRE_BLUE, 2);
+ _gem.remove();
+ if (R2_GLOBALS.getFlag(36))
+ R2_GLOBALS._player.setVisage(20);
+ else
+ R2_GLOBALS._player.setVisage(22);
+
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ // This is a hack to work around a pathfinding issue. original destination is (218, 165)
+ Common::Point pt(128, 165);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ }
+ break;
+ case 1968:
+ R2_GLOBALS._player.enableControl();
+ R2_INVENTORY.setObjectScene(R2_ANCIENT_SCROLLS, 2);
+ _scrolls.setFrame(2);
+ if (R2_GLOBALS.getFlag(36))
+ R2_GLOBALS._player.setVisage(20);
+ else
+ R2_GLOBALS._player.setVisage(22);
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ break;
+ default:
+ R2_GLOBALS._player.enableControl(CURSOR_WALK);
+ break;
+ }
+}
+
+void Scene1950::process(Event &event) {
+ if ( (event.eventType == EVENT_BUTTON_DOWN)
+ && (R2_GLOBALS._player._uiEnabled)
+ && (R2_GLOBALS._events.getCursor() == R2_SOAKED_FACEMASK)
+ && (R2_GLOBALS._player._bounds.contains(event.mousePos))
+ && (R2_INVENTORY.getObjectScene(R2_SCRITH_KEY) == 0)) {
+ event.handled = true;
+ R2_GLOBALS._player.disableControl();
+ _shaftExit._enabled = false;
+ _doorExit._enabled = false;
+ _sceneMode = 1959;
+ setAction(&_sequenceManager, this, 1959, &R2_GLOBALS._player, NULL);
+ }
+
+ Scene::process(event);
+}
+
+} // End of namespace Ringworld2
+} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_vampire.h b/engines/tsage/ringworld2/ringworld2_vampire.h
new file mode 100644
index 0000000000..ca7aa34544
--- /dev/null
+++ b/engines/tsage/ringworld2/ringworld2_vampire.h
@@ -0,0 +1,179 @@
+/* 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.
+ *
+ */
+
+#ifndef TSAGE_RINGWORLD2_VAMPIRE_H
+#define TSAGE_RINGWORLD2_VAMPIRE_H
+
+#include "tsage/events.h"
+#include "tsage/core.h"
+#include "tsage/scenes.h"
+#include "tsage/globals.h"
+#include "tsage/sound.h"
+#include "tsage/ringworld2/ringworld2_logic.h"
+
+namespace TsAGE {
+
+namespace Ringworld2 {
+
+using namespace TsAGE;
+
+class Scene1950 : public SceneExt {
+ /* Windows */
+ class KeypadWindow: public ModalWindow {
+ public:
+ class KeypadButton : public SceneActor {
+ public:
+ int _buttonIndex;
+ bool _pressed;
+ bool _toggled;
+
+ KeypadButton();
+ void synchronize(Serializer &s);
+
+ void init(int indx);
+ virtual void process(Event &event);
+ virtual bool startAction(CursorType action, Event &event);
+ };
+
+ SceneActor _areaActor;
+ KeypadButton _buttons[16];
+
+ int _buttonIndex;
+
+ KeypadWindow();
+ virtual void synchronize(Serializer &s);
+ virtual void remove();
+ virtual void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY);
+ virtual void setup3(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
+ };
+
+ class Keypad : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+
+ /* Actors */
+ class Door : public SceneActor {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class Scrolls : public SceneActor {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class Gem : public SceneActor {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class Vampire : public SceneActor {
+ public:
+ Common::Point _deadPosition;
+ int _deltaX;
+ int _deltaY;
+ int _vampireMode;
+
+ Vampire();
+ void synchronize(Serializer &s);
+
+ virtual void signal();
+ virtual bool startAction(CursorType action, Event &event);
+ };
+
+ /* Exits */
+ class NorthExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class UpExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class EastExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class DownExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class SouthExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class WestExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class ShaftExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+ class DoorExit : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+private:
+ void initArea();
+ void enterArea();
+ void doButtonPress(int indx);
+public:
+ NamedHotspot _background;
+ Keypad _keypad;
+ SceneActor _southDoorway;
+ SceneObject _northDoorway;
+ Door _door;
+ Scrolls _scrolls;
+ SceneActor _containmentField;
+ Gem _gem;
+ SceneActor _cube;
+ SceneActor _pulsingLights;
+ Vampire _vampire;
+ KeypadWindow _KeypadWindow;
+ NorthExit _northExit;
+ UpExit _upExit;
+ EastExit _eastExit;
+ DownExit _downExit;
+ SouthExit _southExit;
+ WestExit _westExit;
+ ShaftExit _shaftExit;
+ DoorExit _doorExit;
+ SequenceManager _sequenceManager;
+
+ bool _upExitStyle;
+ bool _removeFlag;
+ bool _vampireActive;
+ Common::Point _vampireDestPos;
+ int _vampireIndex;
+
+ Scene1950();
+ void synchronize(Serializer &s);
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void signal();
+ virtual void process(Event &event);
+};
+
+} // End of namespace Ringworld2
+} // End of namespace TsAGE
+
+#endif
diff --git a/engines/wintermute/POTFILES b/engines/wintermute/POTFILES
new file mode 100644
index 0000000000..e9422415b2
--- /dev/null
+++ b/engines/wintermute/POTFILES
@@ -0,0 +1 @@
+engines/wintermute/detection.cpp
diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp
index fa452cc0d6..b5b12d55f9 100644
--- a/engines/wintermute/base/sound/base_sound.cpp
+++ b/engines/wintermute/base/sound/base_sound.cpp
@@ -89,7 +89,7 @@ bool BaseSound::setSoundSimple() {
_sound->setLooping(_soundLooping);
_sound->setPrivateVolume(_soundPrivateVolume);
_sound->setLoopStart(_soundLoopStart);
- _sound->_freezePaused = _soundFreezePaused;
+ _sound->setFreezePaused(_soundFreezePaused);
if (_soundPlaying) {
return _sound->resume();
} else {
@@ -130,7 +130,7 @@ bool BaseSound::pause(bool freezePaused) {
if (_sound) {
_soundPaused = true;
if (freezePaused) {
- _sound->_freezePaused = true;
+ _sound->setFreezePaused(true);
}
return _sound->pause();
} else {
@@ -150,13 +150,13 @@ bool BaseSound::resume() {
bool BaseSound::persist(BasePersistenceManager *persistMgr) {
if (persistMgr->getIsSaving() && _sound) {
_soundPlaying = _sound->isPlaying();
- _soundLooping = _sound->_looping;
- _soundPrivateVolume = _sound->_privateVolume;
+ _soundLooping = _sound->isLooping();
+ _soundPrivateVolume = _sound->getPrivateVolume();
if (_soundPlaying) {
_soundPosition = _sound->getPosition();
}
- _soundLoopStart = _sound->_loopStart;
- _soundFreezePaused = _sound->_freezePaused;
+ _soundLoopStart = _sound->getLoopStart();
+ _soundFreezePaused = _sound->isFreezePaused();
}
if (persistMgr->getIsSaving()) {
@@ -232,7 +232,7 @@ bool BaseSound::setPrivateVolume(int volume) {
if (!_sound) {
return STATUS_FAILED;
} else {
- _sound->_privateVolume = volume;
+ _sound->setPrivateVolume(volume);
return STATUS_OK;
}
}
@@ -241,7 +241,7 @@ int BaseSound::getVolumePercent() {
if (!_sound) {
return 0;
} else {
- return _sound->_privateVolume * 100 / 255;
+ return _sound->getPrivateVolume() * 100 / 255;
}
}
@@ -249,7 +249,7 @@ int BaseSound::getVolume() {
if (!_sound) {
return 0;
} else {
- return _sound->_privateVolume;
+ return _sound->getPrivateVolume();
}
}
diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp
index 7ec68ea752..5fdac12cef 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.cpp
+++ b/engines/wintermute/base/sound/base_sound_buffer.cpp
@@ -143,8 +143,13 @@ bool BaseSoundBuffer::play(bool looping, uint32 startSample) {
_stream->seek(startSample);
_handle = new Audio::SoundHandle;
if (_looping) {
- Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_stream, 0, DisposeAfterUse::NO);
- g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, _pan, DisposeAfterUse::YES);
+ if (_loopStart != 0) {
+ Audio::AudioStream *loopStream = new Audio::SubLoopingAudioStream(_stream, 0, Audio::Timestamp(_loopStart, _stream->getRate()), _stream->getLength(), DisposeAfterUse::NO);
+ g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, _pan, DisposeAfterUse::YES);
+ } else {
+ Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_stream, 0, DisposeAfterUse::NO);
+ g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, _pan, DisposeAfterUse::YES);
+ }
} else {
g_system->getMixer()->playStream(_type, _handle, _stream, -1, _volume, _pan, DisposeAfterUse::NO);
}
@@ -296,4 +301,24 @@ bool BaseSoundBuffer::applyFX(TSFXType type, float param1, float param2, float p
return STATUS_OK;
}
+int32 BaseSoundBuffer::getPrivateVolume() const {
+ return _privateVolume;
+}
+
+bool BaseSoundBuffer::isLooping() const {
+ return _looping;
+}
+
+bool BaseSoundBuffer::isFreezePaused() const {
+ return _freezePaused;
+}
+
+void BaseSoundBuffer::setFreezePaused(bool freezePaused) {
+ _freezePaused = freezePaused;
+}
+
+Audio::Mixer::SoundType BaseSoundBuffer::getType() const {
+ return _type;
+}
+
} // End of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound_buffer.h b/engines/wintermute/base/sound/base_sound_buffer.h
index 94bc8dc6ad..b3f3046674 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.h
+++ b/engines/wintermute/base/sound/base_sound_buffer.h
@@ -71,23 +71,26 @@ public:
void updateVolume();
void setType(Audio::Mixer::SoundType Type);
+ Audio::Mixer::SoundType getType() const;
bool loadFromFile(const Common::String &filename, bool forceReload = false);
void setStreaming(bool streamed, uint32 numBlocks = 0, uint32 blockSize = 0);
bool applyFX(TSFXType type, float param1, float param2, float param3, float param4);
-
+ int32 getPrivateVolume() const;
+ void setFreezePaused(bool freezePaused);
+ bool isFreezePaused() const;
+ bool isLooping() const;
//HSTREAM _stream;
//HSYNC _sync;
+
+private:
+ Audio::Mixer::SoundType _type;
Audio::SeekableAudioStream *_stream;
Audio::SoundHandle *_handle;
-
bool _freezePaused;
- uint32 _loopStart;
- Audio::Mixer::SoundType _type;
bool _looping;
-
int32 _privateVolume;
-private:
+ uint32 _loopStart;
uint32 _startPos;
Common::String _filename;
bool _streamed;
diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp
index 41cfe5ea62..f1e0c3b1f9 100644
--- a/engines/wintermute/base/sound/base_sound_manager.cpp
+++ b/engines/wintermute/base/sound/base_sound_manager.cpp
@@ -254,9 +254,9 @@ byte BaseSoundMgr::getMasterVolume() {
bool BaseSoundMgr::pauseAll(bool includingMusic) {
for (uint32 i = 0; i < _sounds.size(); i++) {
- if (_sounds[i]->isPlaying() && (_sounds[i]->_type != Audio::Mixer::kMusicSoundType || includingMusic)) {
+ if (_sounds[i]->isPlaying() && (_sounds[i]->getType() != Audio::Mixer::kMusicSoundType || includingMusic)) {
_sounds[i]->pause();
- _sounds[i]->_freezePaused = true;
+ _sounds[i]->setFreezePaused(true);
}
}
@@ -268,9 +268,9 @@ bool BaseSoundMgr::pauseAll(bool includingMusic) {
bool BaseSoundMgr::resumeAll() {
for (uint32 i = 0; i < _sounds.size(); i++) {
- if (_sounds[i]->_freezePaused) {
+ if (_sounds[i]->isFreezePaused()) {
_sounds[i]->resume();
- _sounds[i]->_freezePaused = false;
+ _sounds[i]->setFreezePaused(false);
}
}
diff --git a/engines/zvision/POTFILES b/engines/zvision/POTFILES
new file mode 100644
index 0000000000..48e2782648
--- /dev/null
+++ b/engines/zvision/POTFILES
@@ -0,0 +1 @@
+engines/zvision/detection.cpp
diff --git a/engines/zvision/fonts/truetype_font.cpp b/engines/zvision/fonts/truetype_font.cpp
index ba4d72bde8..45eaeeb2b4 100644
--- a/engines/zvision/fonts/truetype_font.cpp
+++ b/engines/zvision/fonts/truetype_font.cpp
@@ -95,6 +95,7 @@ Graphics::Surface *TruetypeFont::drawTextToSurface(const Common::String &text, u
lines.pop_back();
}
if (lines.size() == 0) {
+ delete surface;
return nullptr;
}