2005-01-09 16:06:29 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2004-2005 The ScummVM project
|
2004-04-09 12:36:06 +00:00
|
|
|
*
|
|
|
|
* 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
|
2004-10-15 06:06:47 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2004-04-09 12:36:06 +00:00
|
|
|
* 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
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2004-04-09 12:36:06 +00:00
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2005-06-24 15:23:51 +00:00
|
|
|
#include "common/stdafx.h"
|
2004-04-09 12:36:06 +00:00
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
#include "backends/fs/fs.h"
|
|
|
|
|
2004-04-09 12:36:06 +00:00
|
|
|
#include "base/gameDetector.h"
|
|
|
|
#include "base/plugins.h"
|
|
|
|
|
|
|
|
#include "common/config-manager.h"
|
2005-08-19 22:12:09 +00:00
|
|
|
#include "common/file.h"
|
|
|
|
#include "common/system.h"
|
2005-10-13 21:12:47 +00:00
|
|
|
#include "common/md5.h"
|
2005-12-10 17:51:40 +00:00
|
|
|
#include "common/savefile.h"
|
2005-08-19 22:12:09 +00:00
|
|
|
|
|
|
|
#include "sound/mixer.h"
|
2004-11-11 13:37:35 +00:00
|
|
|
#include "sound/mididrv.h"
|
2005-10-12 19:15:32 +00:00
|
|
|
#include "sound/voc.h"
|
|
|
|
#include "sound/audiostream.h"
|
2004-04-09 12:36:06 +00:00
|
|
|
|
2005-06-24 16:01:42 +00:00
|
|
|
#include "kyra/kyra.h"
|
|
|
|
#include "kyra/resource.h"
|
2005-08-19 22:12:09 +00:00
|
|
|
#include "kyra/screen.h"
|
2005-06-24 16:01:42 +00:00
|
|
|
#include "kyra/script.h"
|
2005-10-06 11:57:02 +00:00
|
|
|
#include "kyra/seqplayer.h"
|
2005-06-24 16:01:42 +00:00
|
|
|
#include "kyra/sound.h"
|
2005-10-03 20:21:18 +00:00
|
|
|
#include "kyra/sprites.h"
|
2005-08-19 22:12:09 +00:00
|
|
|
#include "kyra/wsamovie.h"
|
2005-12-09 14:52:31 +00:00
|
|
|
#include "kyra/debugger.h"
|
2005-08-19 22:12:09 +00:00
|
|
|
|
|
|
|
using namespace Kyra;
|
2004-10-15 06:06:47 +00:00
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
enum {
|
|
|
|
// We only compute MD5 of the first megabyte of our data files.
|
|
|
|
kMD5FileSizeLimit = 1024 * 1024
|
|
|
|
};
|
|
|
|
|
|
|
|
// Kyra MD5 detection brutally ripped from the Gobliins engine.
|
2004-10-15 06:06:47 +00:00
|
|
|
struct KyraGameSettings {
|
2004-10-16 22:28:29 +00:00
|
|
|
const char *name;
|
|
|
|
const char *description;
|
2005-10-13 21:12:47 +00:00
|
|
|
byte id;
|
2004-10-16 22:28:29 +00:00
|
|
|
uint32 features;
|
2005-10-13 21:12:47 +00:00
|
|
|
const char *md5sum;
|
|
|
|
const char *checkFile;
|
2004-10-16 22:28:29 +00:00
|
|
|
GameSettings toGameSettings() const {
|
|
|
|
GameSettings dummy = { name, description, features };
|
|
|
|
return dummy;
|
|
|
|
}
|
2004-10-15 06:06:47 +00:00
|
|
|
};
|
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
static const KyraGameSettings kyra_games[] = {
|
2005-11-09 22:26:12 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Floppy, English)", GI_KYRA1, GF_ENGLISH | GF_FLOPPY, // english floppy 1.0 from Malice
|
|
|
|
"3c244298395520bb62b5edfe41688879", "GEMCUT.EMC" },
|
2005-10-14 11:25:48 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Floppy, English)", GI_KYRA1, GF_ENGLISH | GF_FLOPPY,
|
2005-10-13 21:12:47 +00:00
|
|
|
"796e44863dd22fa635b042df1bf16673", "GEMCUT.EMC" },
|
2005-10-19 10:29:34 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Floppy, French)", GI_KYRA1, GF_FRENCH | GF_FLOPPY,
|
2005-10-13 21:12:47 +00:00
|
|
|
"abf8eb360e79a6c2a837751fbd4d3d24", "GEMCUT.EMC" },
|
2005-10-19 10:29:34 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Floppy, German)", GI_KYRA1, GF_GERMAN | GF_FLOPPY,
|
2005-10-13 21:12:47 +00:00
|
|
|
"6018e1dfeaca7fe83f8d0b00eb0dd049", "GEMCUT.EMC"},
|
2005-10-19 10:29:34 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Floppy, Spanish)", GI_KYRA1, GF_SPANISH | GF_FLOPPY, // from VooD
|
2005-10-18 19:59:51 +00:00
|
|
|
"8909b41596913b3f5deaf3c9f1017b01", "GEMCUT.EMC"},
|
2005-11-19 00:16:45 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Floppy, Spanish)", GI_KYRA1, GF_SPANISH | GF_FLOPPY, // floppy 1.8 from clemmy
|
|
|
|
"747861d2a9c643c59fdab570df5b9093", "GEMCUT.EMC"},
|
2005-10-14 11:25:48 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (CD, English)", GI_KYRA1, GF_ENGLISH | GF_TALKIE,
|
2005-10-13 21:12:47 +00:00
|
|
|
"fac399fe62f98671e56a005c5e94e39f", "GEMCUT.PAK" },
|
2005-10-14 11:25:48 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (CD, German)", GI_KYRA1, GF_GERMAN | GF_TALKIE,
|
2005-10-13 21:12:47 +00:00
|
|
|
"230f54e6afc007ab4117159181a1c722", "GEMCUT.PAK" },
|
2005-10-14 11:25:48 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (CD, French)", GI_KYRA1, GF_FRENCH | GF_TALKIE,
|
2005-10-13 21:12:47 +00:00
|
|
|
"b037c41768b652a040360ffa3556fd2a", "GEMCUT.PAK" },
|
2005-10-18 19:59:51 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia (Demo)", GI_KYRA1, GF_DEMO | GF_ENGLISH,
|
2005-10-13 21:12:47 +00:00
|
|
|
"fb722947d94897512b13b50cc84fd648", "DEMO1.WSA" },
|
|
|
|
{ 0, 0, 0, 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Keep list of different supported games
|
|
|
|
struct KyraGameList {
|
|
|
|
const char *name;
|
|
|
|
const char *description;
|
|
|
|
uint32 features;
|
|
|
|
GameSettings toGameSettings() const {
|
|
|
|
GameSettings dummy = { name, description, features };
|
|
|
|
return dummy;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const KyraGameList kyra_list[] = {
|
2005-10-18 19:59:51 +00:00
|
|
|
{ "kyra1", "Legend of Kyrandia", 0 },
|
2005-10-13 21:12:47 +00:00
|
|
|
{ 0, 0, 0 }
|
2004-10-15 06:06:47 +00:00
|
|
|
};
|
2004-04-09 12:36:06 +00:00
|
|
|
|
|
|
|
GameList Engine_KYRA_gameList() {
|
2004-10-16 22:28:29 +00:00
|
|
|
GameList games;
|
2005-10-13 21:12:47 +00:00
|
|
|
const KyraGameList *g = kyra_list;
|
|
|
|
|
2004-10-16 22:28:29 +00:00
|
|
|
while (g->name) {
|
|
|
|
games.push_back(g->toGameSettings());
|
|
|
|
g++;
|
|
|
|
}
|
|
|
|
return games;
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DetectedGameList Engine_KYRA_detectGames(const FSList &fslist) {
|
|
|
|
DetectedGameList detectedGames;
|
2005-10-13 21:12:47 +00:00
|
|
|
const KyraGameSettings *g;
|
|
|
|
FSList::const_iterator file;
|
2004-10-15 06:06:47 +00:00
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
// Iterate over all files in the given directory
|
|
|
|
bool isFound = false;
|
|
|
|
for (file = fslist.begin(); file != fslist.end(); file++) {
|
|
|
|
if (file->isDirectory())
|
2004-10-15 06:06:47 +00:00
|
|
|
continue;
|
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
for (g = kyra_games; g->name; g++) {
|
|
|
|
if (scumm_stricmp(file->displayName().c_str(), g->checkFile) == 0)
|
|
|
|
isFound = true;
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
2005-10-13 21:12:47 +00:00
|
|
|
if (isFound)
|
|
|
|
break;
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
if (file == fslist.end())
|
|
|
|
return detectedGames;
|
|
|
|
|
|
|
|
uint8 md5sum[16];
|
|
|
|
char md5str[32 + 1];
|
|
|
|
|
|
|
|
if (Common::md5_file(file->path().c_str(), md5sum, NULL, kMD5FileSizeLimit)) {
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
|
|
sprintf(md5str + i * 2, "%02x", (int)md5sum[i]);
|
|
|
|
}
|
|
|
|
for (g = kyra_games; g->name; g++) {
|
|
|
|
if (strcmp(g->md5sum, (char *)md5str) == 0) {
|
|
|
|
detectedGames.push_back(g->toGameSettings());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (detectedGames.isEmpty()) {
|
2005-10-14 11:25:48 +00:00
|
|
|
debug("Unknown MD5 (%s)! Please report the details (language, platform, etc.) of this game to the ScummVM team\n", md5str);
|
2005-10-13 21:12:47 +00:00
|
|
|
|
|
|
|
const KyraGameList *g1 = kyra_list;
|
|
|
|
while (g1->name) {
|
|
|
|
detectedGames.push_back(g1->toGameSettings());
|
|
|
|
g1++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-10-16 22:28:29 +00:00
|
|
|
return detectedGames;
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
Engine *Engine_KYRA_create(GameDetector *detector, OSystem *system) {
|
|
|
|
return new KyraEngine(detector, system);
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
2005-03-25 17:55:57 +00:00
|
|
|
REGISTER_PLUGIN(KYRA, "Legend of Kyrandia Engine")
|
2004-04-09 12:36:06 +00:00
|
|
|
|
|
|
|
namespace Kyra {
|
2005-08-19 22:12:09 +00:00
|
|
|
|
|
|
|
KyraEngine::KyraEngine(GameDetector *detector, OSystem *system)
|
|
|
|
: Engine(system) {
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm =
|
|
|
|
_seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 =
|
|
|
|
_seq_Demo4 = 0;
|
|
|
|
|
|
|
|
_seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0;
|
|
|
|
_seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0;
|
2005-12-26 14:53:51 +00:00
|
|
|
|
|
|
|
_roomFilenameTable = _characterImageTable = 0;
|
|
|
|
_roomFilenameTableSize = _characterImageTableSize = 0;
|
|
|
|
_itemList = _takenList = _placedList = _droppedList = _noDropList = 0;
|
|
|
|
_itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0;
|
|
|
|
_putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0;
|
|
|
|
_putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0;
|
|
|
|
|
|
|
|
_defaultShapeTable = _healingShapeTable = _healingShape2Table = 0;
|
|
|
|
_defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0;
|
2004-04-09 12:36:06 +00:00
|
|
|
|
|
|
|
// Setup mixer
|
|
|
|
if (!_mixer->isReady()) {
|
|
|
|
warning("Sound initialization failed.");
|
|
|
|
}
|
|
|
|
|
2005-05-11 01:02:33 +00:00
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
|
2005-10-12 19:15:32 +00:00
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
|
2004-04-09 12:36:06 +00:00
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
// Detect game features based on MD5. Again brutally ripped from Gobliins.
|
|
|
|
uint8 md5sum[16];
|
|
|
|
char md5str[32 + 1];
|
|
|
|
|
|
|
|
const KyraGameSettings *g;
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
// Fallback. Maybe we will be able to determine game type from game
|
|
|
|
// data contents
|
2005-10-14 11:25:48 +00:00
|
|
|
_features = 0;
|
2005-10-13 21:12:47 +00:00
|
|
|
|
|
|
|
for (g = kyra_games; g->name; g++) {
|
|
|
|
if (!Common::File::exists(g->checkFile))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (Common::md5_file(g->checkFile, md5sum, ConfMan.get("path").c_str(), kMD5FileSizeLimit)) {
|
|
|
|
for (int j = 0; j < 16; j++) {
|
|
|
|
sprintf(md5str + j*2, "%02x", (int)md5sum[j]);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (strcmp(g->md5sum, (char *)md5str) == 0) {
|
|
|
|
_features = g->features;
|
|
|
|
_game = g->id;
|
|
|
|
|
|
|
|
if (g->description)
|
|
|
|
g_system->setWindowCaption(g->description);
|
|
|
|
|
|
|
|
found = true;
|
|
|
|
break;
|
2005-08-19 22:12:09 +00:00
|
|
|
}
|
2005-10-13 21:12:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
debug("Unknown MD5 (%s)! Please report the details (language, platform, etc.) of this game to the ScummVM team", md5str);
|
2005-10-18 19:59:51 +00:00
|
|
|
_features = GF_LNGUNK;
|
2005-10-14 11:25:48 +00:00
|
|
|
_game = GI_KYRA1;
|
2005-10-18 19:59:51 +00:00
|
|
|
Common::File test;
|
|
|
|
if (test.open("INTRO.VRM")) {
|
|
|
|
_features |= GF_TALKIE;
|
|
|
|
} else {
|
|
|
|
_features |= GF_FLOPPY;
|
|
|
|
}
|
2004-11-11 13:37:35 +00:00
|
|
|
}
|
2004-11-23 00:03:25 +00:00
|
|
|
}
|
|
|
|
|
2004-11-24 00:14:21 +00:00
|
|
|
int KyraEngine::init(GameDetector &detector) {
|
2005-10-12 19:15:32 +00:00
|
|
|
_currentVocFile = 0;
|
2004-11-24 00:14:21 +00:00
|
|
|
_system->beginGFXTransaction();
|
|
|
|
initCommonGFX(detector);
|
|
|
|
_system->initSize(320, 200);
|
|
|
|
_system->endGFXTransaction();
|
|
|
|
|
2005-09-11 14:35:34 +00:00
|
|
|
// for now we prefer MIDI-to-Adlib conversion over native midi
|
2005-12-30 16:36:53 +00:00
|
|
|
int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/);
|
|
|
|
bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
|
2004-11-14 14:11:54 +00:00
|
|
|
|
2005-12-30 16:36:53 +00:00
|
|
|
MidiDriver *driver = MidiDriver::createMidi(midiDriver);
|
2005-12-30 14:18:21 +00:00
|
|
|
if (midiDriver == MD_ADLIB) {
|
2004-11-14 14:11:54 +00:00
|
|
|
// In this case we should play the Adlib tracks, but for now
|
|
|
|
// the automagic MIDI-to-Adlib conversion will do.
|
2005-08-19 22:12:09 +00:00
|
|
|
} else if (native_mt32) {
|
2004-11-14 14:11:54 +00:00
|
|
|
driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
|
2005-08-19 22:12:09 +00:00
|
|
|
}
|
2004-11-14 14:11:54 +00:00
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
_midi = new MusicPlayer(driver, this);
|
|
|
|
assert(_midi);
|
|
|
|
_midi->hasNativeMT32(native_mt32);
|
|
|
|
_midi->setVolume(255);
|
2005-09-11 14:35:34 +00:00
|
|
|
|
2005-12-10 17:51:40 +00:00
|
|
|
_saveFileMan = _system->getSavefileManager();
|
|
|
|
assert(_saveFileMan);
|
2005-08-19 22:12:09 +00:00
|
|
|
_res = new Resource(this);
|
|
|
|
assert(_res);
|
|
|
|
_screen = new Screen(this, _system);
|
|
|
|
assert(_screen);
|
2005-10-03 20:21:18 +00:00
|
|
|
_sprites = new Sprites(this, _system);
|
|
|
|
assert(_sprites);
|
2005-10-06 11:57:02 +00:00
|
|
|
_seq = new SeqPlayer(this, _system);
|
|
|
|
assert(_seq);
|
2005-10-29 18:37:40 +00:00
|
|
|
|
2005-12-10 15:52:38 +00:00
|
|
|
_paletteChanged = 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
_currentCharacter = 0;
|
|
|
|
_characterList = new Character[11];
|
|
|
|
assert(_characterList);
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
memset(&_characterList[i], 0, sizeof(Character));
|
2005-12-24 18:00:35 +00:00
|
|
|
memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems));
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
_characterList[0].sceneId = 5;
|
|
|
|
_characterList[0].height = 48;
|
|
|
|
_characterList[0].facing = 3;
|
|
|
|
_characterList[0].currentAnimFrame = 7;
|
|
|
|
|
|
|
|
_objectQueue = 0;
|
|
|
|
_animStates = new AnimObject[31];
|
|
|
|
assert(_animStates);
|
2005-11-26 16:37:20 +00:00
|
|
|
memset(_animStates, 0, sizeof(AnimObject)*31);
|
2005-10-29 18:37:40 +00:00
|
|
|
_charactersAnimState = &_animStates[0];
|
2005-11-10 14:08:50 +00:00
|
|
|
_sprites->_animObjects = &_animStates[5];
|
2005-10-30 19:58:51 +00:00
|
|
|
_animItems = &_animStates[16];
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
_scriptInterpreter = new ScriptHelper(this);
|
|
|
|
assert(_scriptInterpreter);
|
|
|
|
|
|
|
|
_npcScriptData = new ScriptData;
|
|
|
|
memset(_npcScriptData, 0, sizeof(ScriptData));
|
|
|
|
assert(_npcScriptData);
|
2005-12-09 23:02:16 +00:00
|
|
|
_npcScript = new ScriptState;
|
|
|
|
assert(_npcScript);
|
|
|
|
memset(_npcScript, 0, sizeof(ScriptState));
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
_scriptMain = new ScriptState;
|
|
|
|
assert(_scriptMain);
|
|
|
|
memset(_scriptMain, 0, sizeof(ScriptState));
|
|
|
|
|
|
|
|
_scriptClickData = new ScriptData;
|
|
|
|
assert(_scriptClickData);
|
|
|
|
memset(_scriptClickData, 0, sizeof(ScriptData));
|
|
|
|
_scriptClick = new ScriptState;
|
|
|
|
assert(_scriptClick);
|
|
|
|
memset(_scriptClick, 0, sizeof(ScriptState));
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
_debugger = new Debugger(this);
|
|
|
|
assert(_debugger);
|
2005-10-29 18:37:40 +00:00
|
|
|
memset(_shapes, 0, sizeof(_shapes));
|
|
|
|
memset(_wsaObjects, 0, sizeof(_wsaObjects));
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
memset(_flagsTable, 0, sizeof(_flagsTable));
|
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
_fastMode = false;
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag = false;
|
|
|
|
_abortWalkFlag2 = false;
|
2005-08-19 22:12:09 +00:00
|
|
|
_talkCoords.y = 0x88;
|
|
|
|
_talkCoords.x = 0;
|
|
|
|
_talkCoords.w = 0;
|
2005-08-31 20:14:20 +00:00
|
|
|
_talkMessageY = 0xC;
|
|
|
|
_talkMessageH = 0;
|
|
|
|
_talkMessagePrinted = false;
|
2005-12-09 14:52:31 +00:00
|
|
|
_talkingCharNum = -1;
|
2005-11-10 14:08:50 +00:00
|
|
|
_charSayUnk3 = -1;
|
2005-10-30 19:58:51 +00:00
|
|
|
_mouseX = _mouseY = -1;
|
2005-12-09 14:52:31 +00:00
|
|
|
memset(_currSentenceColor, 0, 3);
|
|
|
|
_startSentencePalIndex = -1;
|
|
|
|
_fadeText = false;
|
2005-12-24 18:00:35 +00:00
|
|
|
_noDrawShapesFlag = 0;
|
2005-12-09 14:52:31 +00:00
|
|
|
|
2005-12-31 15:41:37 +00:00
|
|
|
_cauldronState = 0;
|
|
|
|
|
2005-12-29 22:18:40 +00:00
|
|
|
_brandonStatusBit = 0;
|
|
|
|
_brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10;
|
2005-10-29 18:37:40 +00:00
|
|
|
_brandonPosX = _brandonPosY = -1;
|
|
|
|
_brandonDrawFrame = 113;
|
2005-12-26 14:53:51 +00:00
|
|
|
_deathHandler = 0xFF;
|
2005-12-28 21:34:40 +00:00
|
|
|
_poisonDeathCounter = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
memset(_itemTable, 0, sizeof(_itemTable));
|
|
|
|
memset(_exitList, 0xFFFF, sizeof(_exitList));
|
|
|
|
_exitListPtr = 0;
|
2005-11-26 16:37:20 +00:00
|
|
|
_pathfinderFlag = _pathfinderFlag2 = 0;
|
2005-11-10 14:08:50 +00:00
|
|
|
_lastFindWayRet = 0;
|
2005-11-09 22:26:12 +00:00
|
|
|
_sceneChangeState = _loopFlag2 = 0;
|
2005-11-11 22:17:06 +00:00
|
|
|
_timerNextRun = 0;
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
_movFacingTable = new int[150];
|
|
|
|
assert(_movFacingTable);
|
2005-11-01 14:19:50 +00:00
|
|
|
_movFacingTable[0] = 8;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
_configTalkspeed = 1;
|
2005-11-18 23:55:31 +00:00
|
|
|
|
|
|
|
_marbleVaseItem = -1;
|
2005-12-24 18:00:35 +00:00
|
|
|
memset(_foyerItemTable, -1, sizeof(_foyerItemTable));
|
2005-11-18 23:55:31 +00:00
|
|
|
_mouseState = _itemInHand = -1;
|
|
|
|
_handleInput = false;
|
2005-11-27 10:02:23 +00:00
|
|
|
|
|
|
|
_currentRoom = 0xFFFF;
|
2005-12-09 23:02:16 +00:00
|
|
|
_scenePhasingFlag = 0;
|
2005-12-08 17:19:18 +00:00
|
|
|
_lastProcessedItem = 0;
|
|
|
|
_lastProcessedItemHeight = 16;
|
2005-12-10 19:02:56 +00:00
|
|
|
|
|
|
|
_hidPage = _screenPage = 0;
|
2005-12-13 16:56:33 +00:00
|
|
|
|
|
|
|
_unkScreenVar1 = 1;
|
|
|
|
_unkScreenVar2 = 0;
|
|
|
|
_unkScreenVar3 = 0;
|
2005-12-22 18:14:52 +00:00
|
|
|
|
|
|
|
memset(_specialPalettes, 0, sizeof(_specialPalettes));
|
2005-12-24 18:00:35 +00:00
|
|
|
_mousePressFlag = false;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2004-11-23 00:03:25 +00:00
|
|
|
return 0;
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
KyraEngine::~KyraEngine() {
|
2005-12-09 14:52:31 +00:00
|
|
|
delete _debugger;
|
2005-10-03 20:21:18 +00:00
|
|
|
delete _sprites;
|
2005-08-19 22:12:09 +00:00
|
|
|
delete _screen;
|
|
|
|
delete _res;
|
|
|
|
delete _midi;
|
2005-12-10 17:51:40 +00:00
|
|
|
delete _saveFileMan;
|
2005-10-06 11:57:02 +00:00
|
|
|
delete _seq;
|
2005-10-29 18:37:40 +00:00
|
|
|
delete _scriptInterpreter;
|
|
|
|
|
|
|
|
delete _npcScriptData;
|
|
|
|
delete _scriptMain;
|
|
|
|
|
|
|
|
delete _scriptClickData;
|
|
|
|
delete _scriptClick;
|
|
|
|
|
|
|
|
delete [] _animStates;
|
|
|
|
delete [] _characterList;
|
2005-10-22 00:24:07 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
delete [] _movFacingTable;
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
free(_buttonShape0);
|
|
|
|
free(_buttonShape1);
|
|
|
|
free(_buttonShape2);
|
|
|
|
free(_buttonShape3);
|
|
|
|
free(_buttonShape4);
|
|
|
|
free(_buttonShape5);
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
for (int i = 0; i < ARRAYSIZE(_shapes); ++i) {
|
|
|
|
if (_shapes[i] != 0) {
|
|
|
|
free(_shapes[i]);
|
|
|
|
for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) {
|
|
|
|
if (_shapes[i2] == _shapes[i] && i2 != i) {
|
|
|
|
_shapes[i2] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) {
|
|
|
|
free(_sceneAnimTable[i]);
|
2005-10-22 00:24:07 +00:00
|
|
|
}
|
2005-12-10 19:02:56 +00:00
|
|
|
free(_unkPtr1);
|
|
|
|
free(_unkPtr2);
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::errorString(const char *buf1, char *buf2) {
|
|
|
|
strcpy(buf2, buf1);
|
|
|
|
}
|
|
|
|
|
2004-11-23 00:03:25 +00:00
|
|
|
int KyraEngine::go() {
|
2005-08-19 22:12:09 +00:00
|
|
|
_quitFlag = false;
|
2005-09-08 19:09:52 +00:00
|
|
|
uint32 sz;
|
2005-09-10 06:48:34 +00:00
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
res_loadResources();
|
2005-10-13 21:12:47 +00:00
|
|
|
if (_features & GF_FLOPPY) {
|
2005-09-10 06:48:34 +00:00
|
|
|
_screen->loadFont(Screen::FID_6_FNT, _res->fileData("6.FNT", &sz));
|
|
|
|
}
|
2005-09-08 19:09:52 +00:00
|
|
|
_screen->loadFont(Screen::FID_8_FNT, _res->fileData("8FAT.FNT", &sz));
|
2005-09-02 11:12:09 +00:00
|
|
|
_screen->setScreenDim(0);
|
2005-09-10 06:40:20 +00:00
|
|
|
|
2005-10-03 20:21:18 +00:00
|
|
|
_abortIntroFlag = false;
|
|
|
|
|
2005-10-13 21:12:47 +00:00
|
|
|
if (_features & GF_DEMO) {
|
2005-09-10 06:40:20 +00:00
|
|
|
seq_demo();
|
|
|
|
} else {
|
2005-11-10 14:08:50 +00:00
|
|
|
setGameFlag(0xF3);
|
|
|
|
setGameFlag(0xFD);
|
|
|
|
setGameFlag(0xEF);
|
2005-09-10 06:40:20 +00:00
|
|
|
seq_intro();
|
|
|
|
startup();
|
2005-11-10 14:08:50 +00:00
|
|
|
resetGameFlag(0xEF);
|
2005-09-10 06:40:20 +00:00
|
|
|
mainLoop();
|
|
|
|
}
|
2005-11-10 14:08:50 +00:00
|
|
|
quitGame();
|
2005-08-19 22:12:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2004-11-11 13:37:35 +00:00
|
|
|
|
2005-09-10 00:15:40 +00:00
|
|
|
void KyraEngine::startup() {
|
|
|
|
debug(9, "KyraEngine::startup()");
|
|
|
|
static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 };
|
|
|
|
_screen->setTextColorMap(colorMap);
|
2005-09-10 20:03:53 +00:00
|
|
|
// _screen->setFont(Screen::FID_6_FNT);
|
2005-09-10 00:15:40 +00:00
|
|
|
_screen->setAnimBlockPtr(3750);
|
2005-10-29 18:37:40 +00:00
|
|
|
memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
|
2005-10-22 00:24:07 +00:00
|
|
|
loadMouseShapes();
|
2005-10-29 18:37:40 +00:00
|
|
|
_currentCharacter = &_characterList[0];
|
|
|
|
for (int i = 1; i < 5; ++i)
|
|
|
|
setCharacterDefaultFrame(i);
|
|
|
|
for (int i = 5; i <= 10; ++i)
|
|
|
|
setCharactersPositions(i);
|
|
|
|
setCharactersHeight();
|
|
|
|
resetBrandonPosionFlags();
|
|
|
|
_maskBuffer = _screen->getPagePtr(5);
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
// XXX
|
|
|
|
for (int i = 0; i < 0x0C; ++i) {
|
|
|
|
int size = _screen->getRectSize(3, 24);
|
|
|
|
_shapes[365+i] = (byte*)malloc(size);
|
|
|
|
}
|
2005-12-10 15:52:38 +00:00
|
|
|
_unkPtr1 = (uint8*)malloc(_screen->getRectSize(1, 144));
|
|
|
|
memset(_unkPtr1, 0, _screen->getRectSize(1, 144));
|
|
|
|
_unkPtr2 = (uint8*)malloc(_screen->getRectSize(1, 144));
|
|
|
|
memset(_unkPtr2, 0, _screen->getRectSize(1, 144));
|
|
|
|
_shapes[0] = (uint8*)malloc(_screen->getRectSize(3, 24));
|
2005-10-29 18:37:40 +00:00
|
|
|
memset(_shapes[0], 0, _screen->getRectSize(3, 24));
|
2005-12-10 15:52:38 +00:00
|
|
|
_shapes[1] = (uint8*)malloc(_screen->getRectSize(4, 32));
|
2005-10-29 18:37:40 +00:00
|
|
|
memset(_shapes[1], 0, _screen->getRectSize(4, 32));
|
2005-12-10 15:52:38 +00:00
|
|
|
_shapes[2] = (uint8*)malloc(_screen->getRectSize(8, 69));
|
2005-10-29 18:37:40 +00:00
|
|
|
memset(_shapes[2], 0, _screen->getRectSize(8, 69));
|
2005-12-10 15:52:38 +00:00
|
|
|
_shapes[3] = (uint8*)malloc(_screen->getRectSize(8, 69));
|
2005-10-29 18:37:40 +00:00
|
|
|
memset(_shapes[3], 0, _screen->getRectSize(8, 69));
|
|
|
|
for (int i = 0; i < _roomTableSize; ++i) {
|
|
|
|
for (int item = 0; item < 12; ++item) {
|
|
|
|
_roomTable[i].itemsTable[item] = 0xFF;
|
2005-12-08 17:19:18 +00:00
|
|
|
_roomTable[i].itemsXPos[item] = 0xFFFF;
|
|
|
|
_roomTable[i].itemsYPos[item] = 0xFF;
|
2005-10-29 18:37:40 +00:00
|
|
|
_roomTable[i].unkField3[item] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loadCharacterShapes();
|
|
|
|
loadSpecialEffectShapes();
|
|
|
|
loadItems();
|
2005-12-24 18:00:35 +00:00
|
|
|
loadButtonShapes();
|
|
|
|
initMainButtonList();
|
2005-10-29 18:37:40 +00:00
|
|
|
loadMainScreen();
|
2005-11-11 22:17:06 +00:00
|
|
|
setupTimers();
|
2005-10-29 18:37:40 +00:00
|
|
|
loadPalette("PALETTE.COL", _screen->_currentPalette);
|
2005-11-11 22:17:06 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
// XXX
|
|
|
|
initAnimStateList();
|
|
|
|
setCharactersInDefaultScene();
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
_gameSpeed = 50;
|
2005-11-11 22:17:06 +00:00
|
|
|
_tickLength = (uint8)(1000.0 / _gameSpeed);
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, _opcodeTable, _opcodeTableSize, 0)) {
|
|
|
|
error("Could not load \"_STARTUP.EMC\" script");
|
|
|
|
}
|
|
|
|
_scriptInterpreter->initScript(_scriptMain, _npcScriptData);
|
|
|
|
if (!_scriptInterpreter->startScript(_scriptMain, 0)) {
|
|
|
|
error("Could not start script function 0 of script \"_STARTUP.EMC\"");
|
|
|
|
}
|
|
|
|
while (_scriptInterpreter->validScript(_scriptMain)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptMain);
|
|
|
|
}
|
|
|
|
|
|
|
|
_scriptInterpreter->unloadScript(_npcScriptData);
|
|
|
|
if (!_scriptInterpreter->loadScript("_NPC.EMC", _npcScriptData, _opcodeTable, _opcodeTableSize, 0)) {
|
|
|
|
error("Could not load \"_NPC.EMC\" script");
|
|
|
|
}
|
|
|
|
|
|
|
|
snd_playTheme(1);
|
2005-11-09 22:26:12 +00:00
|
|
|
snd_setSoundEffectFile(1);
|
2005-10-29 18:37:40 +00:00
|
|
|
enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1);
|
2005-09-10 00:15:40 +00:00
|
|
|
}
|
|
|
|
|
2005-12-20 10:58:07 +00:00
|
|
|
void KyraEngine::delay(uint32 amount, bool update) {
|
2005-10-03 20:21:18 +00:00
|
|
|
OSystem::Event event;
|
2005-12-10 17:51:40 +00:00
|
|
|
char saveLoadSlot[20];
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
_mousePressFlag = false;
|
2005-10-03 20:21:18 +00:00
|
|
|
uint32 start = _system->getMillis();
|
|
|
|
do {
|
|
|
|
while (_system->pollEvent(event)) {
|
|
|
|
switch (event.type) {
|
|
|
|
case OSystem::EVENT_KEYDOWN:
|
|
|
|
if (event.kbd.keycode == 'q' || event.kbd.keycode == 27) {
|
|
|
|
_quitFlag = true;
|
2005-12-09 14:52:31 +00:00
|
|
|
} else if (event.kbd.keycode == 'd' && !_debugger->isAttached()) {
|
|
|
|
_debugger->attach();
|
2005-12-10 17:51:40 +00:00
|
|
|
} else if (event.kbd.keycode >= '0' && event.kbd.keycode <= '9' &&
|
|
|
|
(event.kbd.flags == OSystem::KBD_CTRL || event.kbd.flags == OSystem::KBD_ALT)) {
|
|
|
|
sprintf(saveLoadSlot, "KYRA1.00%i", event.kbd.keycode - '0');
|
|
|
|
if (event.kbd.flags == OSystem::KBD_CTRL)
|
|
|
|
saveGame(saveLoadSlot, saveLoadSlot);
|
|
|
|
else
|
|
|
|
loadGame(saveLoadSlot);
|
|
|
|
} else if (event.kbd.flags == OSystem::KBD_CTRL && event.kbd.keycode == 'f') {
|
|
|
|
_fastMode = !_fastMode;
|
2005-10-03 20:21:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2005-10-22 00:24:07 +00:00
|
|
|
case OSystem::EVENT_MOUSEMOVE:
|
|
|
|
_mouseX = event.mouse.x;
|
|
|
|
_mouseY = event.mouse.y;
|
|
|
|
break;
|
2005-10-03 20:21:18 +00:00
|
|
|
case OSystem::EVENT_QUIT:
|
2005-11-11 22:17:06 +00:00
|
|
|
quitGame();
|
2005-10-03 20:21:18 +00:00
|
|
|
break;
|
2005-11-18 23:55:31 +00:00
|
|
|
case OSystem::EVENT_LBUTTONDOWN:
|
2005-12-24 18:00:35 +00:00
|
|
|
_mousePressFlag = true;
|
2005-12-13 15:10:20 +00:00
|
|
|
if (_abortWalkFlag2) {
|
|
|
|
_abortWalkFlag = true;
|
|
|
|
_mouseX = event.mouse.x;
|
|
|
|
_mouseY = event.mouse.y;
|
|
|
|
}
|
2005-11-18 23:55:31 +00:00
|
|
|
if (_handleInput) {
|
|
|
|
_mouseX = event.mouse.x;
|
|
|
|
_mouseY = event.mouse.y;
|
|
|
|
_handleInput = false;
|
|
|
|
processInput(_mouseX, _mouseY);
|
|
|
|
_handleInput = true;
|
|
|
|
}
|
|
|
|
break;
|
2005-10-03 20:21:18 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-12-09 14:52:31 +00:00
|
|
|
|
|
|
|
if (_debugger->isAttached())
|
|
|
|
_debugger->onFrame();
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
_sprites->updateSceneAnims();
|
2005-12-20 10:58:07 +00:00
|
|
|
if (update)
|
|
|
|
updateAllObjectShapes();
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
//XXX
|
|
|
|
}
|
|
|
|
|
2005-10-03 20:21:18 +00:00
|
|
|
if (amount > 0) {
|
|
|
|
_system->delayMillis((amount > 10) ? 10 : amount);
|
|
|
|
}
|
2005-12-10 17:51:40 +00:00
|
|
|
} while (!_fastMode && _system->getMillis() < start + amount);
|
2005-10-03 20:21:18 +00:00
|
|
|
}
|
|
|
|
|
2005-12-10 19:02:56 +00:00
|
|
|
void KyraEngine::waitForEvent() {
|
|
|
|
bool finished = false;
|
|
|
|
OSystem::Event event;
|
|
|
|
while (!finished) {
|
|
|
|
while (_system->pollEvent(event)) {
|
|
|
|
switch (event.type) {
|
|
|
|
case OSystem::EVENT_KEYDOWN:
|
|
|
|
finished = true;
|
|
|
|
break;
|
|
|
|
case OSystem::EVENT_MOUSEMOVE:
|
|
|
|
_mouseX = event.mouse.x;
|
|
|
|
_mouseY = event.mouse.y;
|
|
|
|
break;
|
|
|
|
case OSystem::EVENT_QUIT:
|
|
|
|
quitGame();
|
|
|
|
break;
|
|
|
|
case OSystem::EVENT_LBUTTONDOWN:
|
|
|
|
finished = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_debugger->isAttached())
|
|
|
|
_debugger->onFrame();
|
|
|
|
|
|
|
|
_system->delayMillis(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-10 00:15:40 +00:00
|
|
|
void KyraEngine::mainLoop() {
|
|
|
|
debug(9, "KyraEngine::mainLoop()");
|
2005-10-03 20:21:18 +00:00
|
|
|
|
|
|
|
while (!_quitFlag) {
|
|
|
|
int32 frameTime = (int32)_system->getMillis();
|
2005-12-29 22:18:40 +00:00
|
|
|
|
|
|
|
if (_brandonStatusBit & 2) {
|
|
|
|
if (_brandonStatusBit0x02Flag)
|
|
|
|
animRefreshNPC(0);
|
|
|
|
}
|
|
|
|
if (_brandonStatusBit & 0x20) {
|
|
|
|
if (_brandonStatusBit0x20Flag) {
|
|
|
|
animRefreshNPC(0);
|
|
|
|
_brandonStatusBit0x20Flag = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
processButtonList(_buttonList);
|
2005-11-18 23:55:31 +00:00
|
|
|
updateMousePointer();
|
2005-11-11 22:17:06 +00:00
|
|
|
updateGameTimers();
|
2005-11-18 23:55:31 +00:00
|
|
|
_sprites->updateSceneAnims();
|
|
|
|
updateAllObjectShapes();
|
2005-12-09 14:52:31 +00:00
|
|
|
updateTextFade();
|
2005-10-03 20:21:18 +00:00
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
_handleInput = true;
|
2005-12-20 10:58:07 +00:00
|
|
|
delay((frameTime + _gameSpeed) - _system->getMillis(), true);
|
2005-11-18 23:55:31 +00:00
|
|
|
_handleInput = false;
|
2005-10-03 20:21:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
void KyraEngine::quitGame() {
|
|
|
|
res_unloadResources();
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
wsa_close(_wsaObjects[i]);
|
|
|
|
|
|
|
|
_system->quit();
|
|
|
|
}
|
|
|
|
|
2005-10-03 20:21:18 +00:00
|
|
|
void KyraEngine::loadPalette(const char *filename, uint8 *palData) {
|
|
|
|
debug(9, "KyraEngine::loadPalette('%s' 0x%X)", filename, palData);
|
|
|
|
uint32 fileSize = 0;
|
|
|
|
uint8 *srcData = _res->fileData(filename, &fileSize);
|
|
|
|
|
|
|
|
if (palData && fileSize) {
|
2005-10-13 21:12:47 +00:00
|
|
|
debug(9, "Loading a palette of size %i from '%s'", fileSize, filename);
|
2005-10-03 20:21:18 +00:00
|
|
|
memcpy(palData, srcData, fileSize);
|
|
|
|
}
|
2005-11-10 14:08:50 +00:00
|
|
|
delete[] srcData;
|
2005-09-10 00:15:40 +00:00
|
|
|
}
|
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
void KyraEngine::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData) {
|
|
|
|
debug(9, "KyraEngine::copyBitmap('%s', %d, %d, 0x%X)", filename, tempPage, dstPage, palData);
|
|
|
|
uint32 fileSize;
|
|
|
|
uint8 *srcData = _res->fileData(filename, &fileSize);
|
|
|
|
uint8 compType = srcData[2];
|
|
|
|
uint32 imgSize = READ_LE_UINT32(srcData + 4);
|
|
|
|
uint16 palSize = READ_LE_UINT16(srcData + 8);
|
|
|
|
if (palData && palSize) {
|
2005-10-03 20:21:18 +00:00
|
|
|
debug(9, "Loading a palette of size %i from %s", palSize, filename);
|
2005-08-19 22:12:09 +00:00
|
|
|
memcpy(palData, srcData + 10, palSize);
|
2004-10-15 06:06:47 +00:00
|
|
|
}
|
2005-08-22 15:39:07 +00:00
|
|
|
uint8 *srcPtr = srcData + 10 + palSize;
|
2005-08-19 22:12:09 +00:00
|
|
|
uint8 *dstData = _screen->getPagePtr(dstPage);
|
|
|
|
switch (compType) {
|
|
|
|
case 0:
|
2005-08-22 15:39:07 +00:00
|
|
|
memcpy(dstData, srcPtr, imgSize);
|
2005-08-19 22:12:09 +00:00
|
|
|
break;
|
|
|
|
case 3:
|
2005-08-22 15:39:07 +00:00
|
|
|
Screen::decodeFrame3(srcPtr, dstData, imgSize);
|
2005-08-19 22:12:09 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
2005-08-22 15:39:07 +00:00
|
|
|
Screen::decodeFrame4(srcPtr, dstData, imgSize);
|
2005-08-19 22:12:09 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unhandled bitmap compression %d", compType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
delete[] srcData;
|
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
void KyraEngine::waitTicks(int ticks) {
|
|
|
|
debug(9, "KyraEngine::waitTicks(%d)", ticks);
|
|
|
|
const uint32 end = _system->getMillis() + ticks * 1000 / 60;
|
|
|
|
do {
|
|
|
|
OSystem::Event event;
|
|
|
|
while (_system->pollEvent(event)) {
|
2004-12-05 17:42:20 +00:00
|
|
|
switch (event.type) {
|
2005-08-19 22:12:09 +00:00
|
|
|
case OSystem::EVENT_QUIT:
|
|
|
|
_quitFlag = true;
|
2005-11-10 14:08:50 +00:00
|
|
|
quitGame();
|
2005-08-19 22:12:09 +00:00
|
|
|
break;
|
|
|
|
case OSystem::EVENT_KEYDOWN:
|
|
|
|
if (event.kbd.flags == OSystem::KBD_CTRL) {
|
|
|
|
if (event.kbd.keycode == 'f') {
|
|
|
|
_fastMode = !_fastMode;
|
|
|
|
}
|
2005-10-03 20:21:18 +00:00
|
|
|
} else if (event.kbd.keycode == 13 || event.kbd.keycode == 32 || event.kbd.keycode == 27) {
|
|
|
|
_abortIntroFlag = true;
|
2005-08-19 22:12:09 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2004-10-15 06:06:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_system->delayMillis(10);
|
2005-08-19 22:12:09 +00:00
|
|
|
} while (!_fastMode && _system->getMillis() < end);
|
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
void KyraEngine::delayWithTicks(int ticks) {
|
|
|
|
uint32 nextTime = _system->getMillis() + ticks * _tickLength;
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
_sprites->updateSceneAnims();
|
|
|
|
updateAllObjectShapes();
|
|
|
|
//if (_currentCharacter->sceneId == 210) {
|
|
|
|
// updateKyragemFading();
|
|
|
|
// seq_playEnd();
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-10 06:40:20 +00:00
|
|
|
void KyraEngine::seq_demo() {
|
|
|
|
debug(9, "KyraEngine::seq_demo()");
|
|
|
|
|
2005-09-12 10:49:52 +00:00
|
|
|
snd_playTheme(MUSIC_INTRO, 2);
|
|
|
|
|
|
|
|
loadBitmap("START.CPS", 7, 7, _screen->_currentPalette);
|
|
|
|
_screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
|
|
|
|
_system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
|
|
|
|
_screen->fadeFromBlack();
|
|
|
|
waitTicks(60);
|
|
|
|
_screen->fadeToBlack();
|
2005-09-10 06:40:20 +00:00
|
|
|
|
|
|
|
_screen->clearPage(0);
|
2005-09-10 07:46:18 +00:00
|
|
|
loadBitmap("TOP.CPS", 7, 7, NULL);
|
2005-09-10 06:40:20 +00:00
|
|
|
loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
|
|
|
|
_screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
|
|
|
|
_screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
|
2005-09-10 07:46:18 +00:00
|
|
|
_system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
|
2005-09-10 06:40:20 +00:00
|
|
|
_screen->fadeFromBlack();
|
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_WestwoodLogo, true);
|
2005-09-10 06:40:20 +00:00
|
|
|
waitTicks(60);
|
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_KyrandiaLogo, true);
|
2005-09-10 06:40:20 +00:00
|
|
|
|
|
|
|
_screen->fadeToBlack();
|
|
|
|
_screen->clearPage(2);
|
|
|
|
_screen->clearPage(0);
|
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_Demo1, true);
|
2005-09-10 06:40:20 +00:00
|
|
|
|
|
|
|
_screen->clearPage(0);
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_Demo2, true);
|
2005-09-10 06:40:20 +00:00
|
|
|
|
|
|
|
_screen->clearPage(0);
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_Demo3, true);
|
2005-09-10 06:40:20 +00:00
|
|
|
|
|
|
|
_screen->clearPage(0);
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_Demo4, true);
|
2005-09-10 06:40:20 +00:00
|
|
|
|
2005-09-12 10:49:52 +00:00
|
|
|
_screen->clearPage(0);
|
|
|
|
loadBitmap("FINAL.CPS", 7, 7, _screen->_currentPalette);
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
_screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
|
|
|
|
_system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
|
|
|
|
_screen->fadeFromBlack();
|
|
|
|
waitTicks(60);
|
|
|
|
_screen->fadeToBlack();
|
2005-10-03 20:21:18 +00:00
|
|
|
_midi->stopMusic();
|
2005-09-10 06:40:20 +00:00
|
|
|
}
|
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
void KyraEngine::seq_intro() {
|
|
|
|
debug(9, "KyraEngine::seq_intro()");
|
2005-10-13 21:12:47 +00:00
|
|
|
if (_features & GF_TALKIE) {
|
2005-10-18 19:59:51 +00:00
|
|
|
_res->loadPakFile("INTRO.VRM");
|
2005-10-12 19:15:32 +00:00
|
|
|
}
|
2005-10-18 19:59:51 +00:00
|
|
|
|
2005-09-08 19:09:52 +00:00
|
|
|
static const IntroProc introProcTable[] = {
|
|
|
|
&KyraEngine::seq_introLogos,
|
2005-10-13 21:12:47 +00:00
|
|
|
&KyraEngine::seq_introStory,
|
2005-10-18 19:59:51 +00:00
|
|
|
&KyraEngine::seq_introMalcolmTree,
|
2005-09-08 19:09:52 +00:00
|
|
|
&KyraEngine::seq_introKallakWriting,
|
2005-10-18 19:59:51 +00:00
|
|
|
&KyraEngine::seq_introKallakMalcolm
|
2005-09-08 19:09:52 +00:00
|
|
|
};
|
2005-10-29 18:37:40 +00:00
|
|
|
_skipIntroFlag = true; // only true if user already saved the game once
|
2005-10-06 11:57:02 +00:00
|
|
|
_seq->setCopyViewOffs(true);
|
2005-09-08 19:09:52 +00:00
|
|
|
_screen->setFont(Screen::FID_8_FNT);
|
2005-09-11 14:35:34 +00:00
|
|
|
snd_playTheme(MUSIC_INTRO, 2);
|
|
|
|
snd_setSoundEffectFile(MUSIC_INTRO);
|
2005-09-09 21:13:43 +00:00
|
|
|
setTalkCoords(144);
|
2005-09-08 19:09:52 +00:00
|
|
|
for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) {
|
|
|
|
(this->*introProcTable[i])();
|
2004-10-15 06:06:47 +00:00
|
|
|
}
|
2005-09-09 21:13:43 +00:00
|
|
|
setTalkCoords(136);
|
2005-09-11 14:35:34 +00:00
|
|
|
waitTicks(30);
|
2005-10-06 11:57:02 +00:00
|
|
|
_seq->setCopyViewOffs(false);
|
2005-10-03 20:21:18 +00:00
|
|
|
_midi->stopMusic();
|
2005-10-13 21:12:47 +00:00
|
|
|
if (_features & GF_TALKIE) {
|
2005-10-19 10:29:34 +00:00
|
|
|
_res->unloadPakFile("INTRO.VRM");
|
2005-10-12 19:15:32 +00:00
|
|
|
}
|
2005-10-18 19:59:51 +00:00
|
|
|
res_unloadResources(RES_INTRO);
|
2005-08-19 22:12:09 +00:00
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
void KyraEngine::seq_introLogos() {
|
|
|
|
debug(9, "KyraEngine::seq_introLogos()");
|
|
|
|
_screen->clearPage(0);
|
2005-09-10 07:46:18 +00:00
|
|
|
loadBitmap("TOP.CPS", 7, 7, NULL);
|
2005-09-08 19:09:52 +00:00
|
|
|
loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
|
2005-08-19 22:12:09 +00:00
|
|
|
_screen->_curPage = 0;
|
|
|
|
_screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
|
|
|
|
_screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
|
2005-09-10 07:46:18 +00:00
|
|
|
_system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
|
2005-08-19 22:12:09 +00:00
|
|
|
_screen->fadeFromBlack();
|
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
if (_seq->playSequence(_seq_WestwoodLogo, _skipIntroFlag)) {
|
|
|
|
_screen->fadeToBlack();
|
|
|
|
_screen->clearPage(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
waitTicks(60);
|
|
|
|
if (_seq->playSequence(_seq_KyrandiaLogo, _skipIntroFlag)) {
|
|
|
|
_screen->fadeToBlack();
|
|
|
|
_screen->clearPage(0);
|
|
|
|
return;
|
2005-08-19 22:12:09 +00:00
|
|
|
}
|
|
|
|
_screen->fillRect(0, 179, 319, 199, 0);
|
|
|
|
|
|
|
|
int y1 = 8;
|
|
|
|
int h1 = 175;
|
|
|
|
int y2 = 176;
|
|
|
|
int h2 = 0;
|
|
|
|
_screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 2);
|
|
|
|
_screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 2);
|
|
|
|
do {
|
|
|
|
if (h1 > 0) {
|
|
|
|
_screen->copyRegion(0, y1, 0, 8, 320, h1, 2, 0);
|
|
|
|
}
|
|
|
|
++y1;
|
|
|
|
--h1;
|
|
|
|
if (h2 > 0) {
|
|
|
|
_screen->copyRegion(0, 64, 0, y2, 320, h2, 4, 0);
|
|
|
|
}
|
|
|
|
--y2;
|
|
|
|
++h2;
|
|
|
|
_screen->updateScreen();
|
|
|
|
waitTicks(1);
|
|
|
|
} while (y2 >= 64);
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_Forest, true);
|
2004-04-09 12:36:06 +00:00
|
|
|
}
|
|
|
|
|
2005-09-08 19:09:52 +00:00
|
|
|
void KyraEngine::seq_introStory() {
|
|
|
|
debug(9, "KyraEngine::seq_introStory()");
|
2005-10-18 19:59:51 +00:00
|
|
|
_screen->clearPage(3);
|
|
|
|
_screen->clearPage(0);
|
2005-10-19 15:59:40 +00:00
|
|
|
if ((_features & GF_ENGLISH) && (_features & GF_TALKIE)) {
|
|
|
|
loadBitmap("TEXT_ENG.CPS", 3, 3, 0);
|
2005-10-18 19:59:51 +00:00
|
|
|
} else if (_features & GF_GERMAN) {
|
|
|
|
loadBitmap("TEXT_GER.CPS", 3, 3, 0);
|
|
|
|
} else if (_features & GF_FRENCH) {
|
|
|
|
loadBitmap("TEXT_FRE.CPS", 3, 3, 0);
|
|
|
|
} else if (_features & GF_SPANISH) {
|
|
|
|
loadBitmap("TEXT_SPA.CPS", 3, 3, 0);
|
2005-10-19 15:59:40 +00:00
|
|
|
} else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY)) {
|
|
|
|
loadBitmap("TEXT.CPS", 3, 3, 0);
|
2005-10-18 19:59:51 +00:00
|
|
|
} else {
|
|
|
|
warning("no story graphics file found");
|
2005-10-13 21:12:47 +00:00
|
|
|
}
|
2005-10-18 19:59:51 +00:00
|
|
|
_screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
waitTicks(360);
|
2005-09-08 19:09:52 +00:00
|
|
|
}
|
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
void KyraEngine::seq_introMalcolmTree() {
|
|
|
|
debug(9, "KyraEngine::seq_introMalcolmTree()");
|
2005-09-08 19:09:52 +00:00
|
|
|
_screen->_curPage = 0;
|
|
|
|
_screen->clearPage(3);
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_MalcolmTree, true);
|
2005-09-08 19:09:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_introKallakWriting() {
|
|
|
|
debug(9, "KyraEngine::seq_introKallakWriting()");
|
2005-10-06 11:57:02 +00:00
|
|
|
_seq->makeHandShapes();
|
2005-09-10 00:15:40 +00:00
|
|
|
_screen->setAnimBlockPtr(5060);
|
2005-09-08 19:09:52 +00:00
|
|
|
_screen->_charWidth = -2;
|
|
|
|
_screen->clearPage(3);
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_KallakWriting, true);
|
2005-09-08 19:09:52 +00:00
|
|
|
}
|
|
|
|
|
2005-10-18 19:59:51 +00:00
|
|
|
void KyraEngine::seq_introKallakMalcolm() {
|
|
|
|
debug(9, "KyraEngine::seq_introKallakMalcolm()");
|
2005-09-08 19:09:52 +00:00
|
|
|
_screen->clearPage(3);
|
2005-10-18 19:59:51 +00:00
|
|
|
_seq->playSequence(_seq_KallakMalcolm, true);
|
2004-10-15 06:06:47 +00:00
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
|
|
|
|
debug(9, "seq_createAmuletJewel(%d, %d, %d, %d)", jewel, page, noSound, drawOnly);
|
|
|
|
const static uint16 specialJewelTable[] = {
|
|
|
|
0x167, 0x162, 0x15D, 0x158, 0x153, 0xFFFF
|
|
|
|
};
|
|
|
|
const static uint16 specialJewelTable1[] = {
|
|
|
|
0x14F, 0x154, 0x159, 0x15E, 0x163, 0xFFFF
|
|
|
|
};
|
|
|
|
const static uint16 specialJewelTable2[] = {
|
|
|
|
0x150, 0x155, 0x15A, 0x15F, 0x164, 0xFFFF
|
|
|
|
};
|
|
|
|
const static uint16 specialJewelTable3[] = {
|
|
|
|
0x151, 0x156, 0x15B, 0x160, 0x165, 0xFFFF
|
|
|
|
};
|
|
|
|
const static uint16 specialJewelTable4[] = {
|
|
|
|
0x152, 0x157, 0x15C, 0x161, 0x166, 0xFFFF
|
|
|
|
};
|
|
|
|
if (!noSound)
|
|
|
|
// snd_playSoundEffect(0x5F)
|
|
|
|
_screen->hideMouse();
|
|
|
|
if (!drawOnly) {
|
|
|
|
for (int i = 0; specialJewelTable[i] != 0xFFFF; ++i) {
|
|
|
|
_screen->drawShape(page, _shapes[4+specialJewelTable[i]], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
delayWithTicks(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint16 *opcodes = 0;
|
|
|
|
switch (jewel - 1) {
|
|
|
|
case 0:
|
|
|
|
opcodes = specialJewelTable1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
opcodes = specialJewelTable2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
opcodes = specialJewelTable3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
opcodes = specialJewelTable4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opcodes) {
|
|
|
|
for (int i = 0; opcodes[i] != 0xFFFF; ++i) {
|
|
|
|
_screen->drawShape(page, _shapes[4+opcodes[i]], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
delayWithTicks(3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->drawShape(page, _shapes[327+jewel], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
_screen->showMouse();
|
|
|
|
setGameFlag(0x55+jewel);
|
|
|
|
}
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
void KyraEngine::seq_brandonHealing() {
|
|
|
|
debug(9, "seq_brandonHealing()");
|
|
|
|
if (!(_deathHandler & 8))
|
|
|
|
return;
|
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
//if (_unkSceneVar == 4 || _unkSceneVar == 6)
|
|
|
|
// return;
|
|
|
|
}
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
assert(_healingShapeTable);
|
|
|
|
setupShapes123(_healingShapeTable, 22, 0);
|
|
|
|
setBrandonAnimSeqSize(3, 48);
|
|
|
|
// snd_playSoundEffect(0x53);
|
|
|
|
for (int i = 123; i <= 144; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
for (int i = 125; i >= 123; --i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
2005-12-28 21:34:40 +00:00
|
|
|
void KyraEngine::seq_brandonHealing2() {
|
|
|
|
debug(9, "seq_brandonHealing2()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
assert(_healingShape2Table);
|
|
|
|
setupShapes123(_healingShape2Table, 30, 0);
|
|
|
|
resetBrandonPoisonFlags();
|
|
|
|
setBrandonAnimSeqSize(3, 48);
|
|
|
|
// snd_playSoundEffect(0x50);
|
|
|
|
for (int i = 123; i <= 152; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
assert(_poisonGone);
|
|
|
|
characterSays(_poisonGone[0], 0, -2);
|
|
|
|
characterSays(_poisonGone[1], 0, -2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_poisonDeathNow(int now) {
|
|
|
|
debug(9, "seq_poisonDeathNow(%d)", now);
|
|
|
|
if (!(_brandonStatusBit & 1))
|
|
|
|
return;
|
|
|
|
++_poisonDeathCounter;
|
|
|
|
if (now)
|
|
|
|
_poisonDeathCounter = 2;
|
|
|
|
if (_poisonDeathCounter >= 2) {
|
|
|
|
// XXX
|
|
|
|
assert(_thePoison);
|
|
|
|
characterSays(_thePoison[0], 0, -2);
|
|
|
|
characterSays(_thePoison[1], 0, -2);
|
|
|
|
seq_poisonDeathNowAnim();
|
|
|
|
_deathHandler = 3;
|
|
|
|
} else {
|
|
|
|
assert(_thePoison);
|
|
|
|
characterSays(_thePoison[2], 0, -2);
|
|
|
|
characterSays(_thePoison[3], 0, -2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_poisonDeathNowAnim() {
|
|
|
|
debug(9, "seq_poisonDeathNowAnim()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
assert(_posionDeathShapeTable);
|
|
|
|
setupShapes123(_posionDeathShapeTable, 20, 0);
|
|
|
|
setBrandonAnimSeqSize(8, 48);
|
|
|
|
|
|
|
|
_currentCharacter->currentAnimFrame = 124;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(30);
|
|
|
|
|
|
|
|
_currentCharacter->currentAnimFrame = 123;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(30);
|
|
|
|
|
|
|
|
for (int i = 125; i <= 139; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
delayWithTicks(60);
|
|
|
|
|
|
|
|
for (int i = 140; i <= 142; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
delayWithTicks(60);
|
|
|
|
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
freeShapes123();
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
_currentCharacter->x1 = _currentCharacter->x2 = -1;
|
|
|
|
_currentCharacter->y1 = _currentCharacter->y2 = -1;
|
|
|
|
preserveAllBackgrounds();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_playFluteAnimation() {
|
|
|
|
debug(9, "seq_playFluteAnimation()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
setupShapes123(_fluteAnimShapeTable, 36, 0);
|
|
|
|
setBrandonAnimSeqSize(3, 75);
|
|
|
|
for (int i = 123; i <= 130; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int delayTime = 0, soundType = 0;
|
|
|
|
if (queryGameFlag(0x85)) {
|
|
|
|
// snd_playSoundEffect(0x63);
|
|
|
|
delayTime = 9;
|
|
|
|
soundType = 3;
|
|
|
|
} else if (queryGameFlag(0x86)) {
|
|
|
|
// snd_playSoundEffect(0x61);
|
|
|
|
delayTime = 2;
|
|
|
|
soundType = 1;
|
|
|
|
} else {
|
|
|
|
// snd_playSoundEffect(0x62);
|
|
|
|
delayTime = 2;
|
|
|
|
soundType = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 131; i <= 158; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(delayTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 126; i >= 123; --i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(delayTime);
|
|
|
|
}
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
|
|
|
|
if (soundType == 1) {
|
|
|
|
assert(_fluteString);
|
|
|
|
characterSays(_fluteString[0], 0, -2);
|
|
|
|
} else if (soundType == 2) {
|
|
|
|
assert(_fluteString);
|
|
|
|
characterSays(_fluteString[1], 0, -2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-29 22:18:40 +00:00
|
|
|
void KyraEngine::seq_winterScroll1() {
|
|
|
|
debug(9, "seq_winterScroll1()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
assert(_winterScrollTable);
|
|
|
|
assert(_winterScroll1Table);
|
|
|
|
assert(_winterScroll2Table);
|
|
|
|
setupShapes123(_winterScrollTable, 7, 0);
|
|
|
|
setBrandonAnimSeqSize(5, 66);
|
|
|
|
|
|
|
|
for (int i = 123; i <= 129; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
freeShapes123();
|
|
|
|
// snd_playSoundEffect(0x20);
|
|
|
|
setupShapes123(_winterScroll1Table, 35, 0);
|
|
|
|
|
|
|
|
for (int i = 123; i <= 146; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_currentCharacter->sceneId == 41 && !queryGameFlag(0xA2)) {
|
|
|
|
// snd_playSoundEffect(0x20);
|
|
|
|
_sprites->_anims[0].play = false;
|
|
|
|
_sprites->_animObjects[0].active = 0;
|
|
|
|
_sprites->_anims[1].play = true;
|
|
|
|
_sprites->_animObjects[1].active = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 147; i <= 157; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_currentCharacter->sceneId == 117 && !queryGameFlag(0xB3)) {
|
|
|
|
for (int i = 0; i <= 7; ++i) {
|
|
|
|
_sprites->_anims[i].play = false;
|
|
|
|
_sprites->_animObjects[i].active = 0;
|
|
|
|
}
|
|
|
|
uint8 tmpPal[768];
|
|
|
|
memcpy(tmpPal, _screen->_currentPalette, 768);
|
|
|
|
memcpy(&tmpPal[684], palTable2()[0], 60);
|
|
|
|
_screen->fadePalette(tmpPal, 72);
|
|
|
|
} else {
|
|
|
|
delayWithTicks(120);
|
|
|
|
}
|
|
|
|
|
|
|
|
freeShapes123();
|
|
|
|
setupShapes123(_winterScroll2Table, 4, 0);
|
|
|
|
|
|
|
|
for (int i = 123; i <= 126; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_winterScroll2() {
|
|
|
|
debug(9, "seq_winterScroll2()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
assert(_winterScrollTable);
|
|
|
|
setupShapes123(_winterScrollTable, 7, 0);
|
|
|
|
setBrandonAnimSeqSize(5, 66);
|
|
|
|
|
|
|
|
for (int i = 123; i <= 128; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
delayWithTicks(120);
|
|
|
|
|
|
|
|
for (int i = 127; i >= 123; --i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_makeBrandonInv() {
|
|
|
|
debug(9, "seq_makeBrandonInv()");
|
|
|
|
if (_deathHandler == 8)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
//if (_unkSceneVar == 4 || _unkSceneVar == 6)
|
|
|
|
// return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
_brandonStatusBit |= 0x20;
|
|
|
|
setTimerCountdown(18, 2700);
|
|
|
|
_brandonStatusBit |= 0x40;
|
|
|
|
// snd_playSoundEffect(0x77);
|
|
|
|
_brandonInvFlag = 0;
|
|
|
|
while (_brandonInvFlag <= 0x100) {
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(10);
|
|
|
|
_brandonInvFlag += 0x10;
|
|
|
|
}
|
|
|
|
_brandonStatusBit &= 0xFFBF;
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_makeBrandonNormal() {
|
|
|
|
debug(9, "seq_makeBrandonNormal()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
_brandonStatusBit |= 0x40;
|
|
|
|
// snd_playSoundEffect(0x77);
|
|
|
|
_brandonInvFlag = 0x100;
|
|
|
|
while (_brandonInvFlag >= 0) {
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(10);
|
|
|
|
_brandonInvFlag -= 0x10;
|
|
|
|
}
|
|
|
|
_brandonStatusBit &= 0xFF9F;
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_makeBrandonNormal2() {
|
|
|
|
debug(9, "seq_makeBrandonNormal2()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
assert(_brandonToWispTable);
|
|
|
|
setupShapes123(_brandonToWispTable, 26, 0);
|
|
|
|
setBrandonAnimSeqSize(5, 48);
|
|
|
|
_brandonStatusBit &= 0xFFFD;
|
|
|
|
// snd_playSoundEffect(0x6C);
|
|
|
|
for (int i = 138; i >= 123; --i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
setBrandonAnimSeqSize(4, 48);
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) {
|
|
|
|
_screen->fadeSpecialPalette(31, 234, 13, 4);
|
|
|
|
} else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186) {
|
|
|
|
_screen->fadeSpecialPalette(14, 228, 15, 4);
|
|
|
|
}
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_makeBrandonWisp() {
|
|
|
|
debug(9, "seq_makeBrandonWisp()");
|
|
|
|
if (_deathHandler == 8)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
//if (_unkSceneVar == 4 || _unkSceneVar == 6)
|
|
|
|
// return;
|
|
|
|
}
|
|
|
|
_screen->hideMouse();
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
assert(_brandonToWispTable);
|
|
|
|
setupShapes123(_brandonToWispTable, 26, 0);
|
|
|
|
setBrandonAnimSeqSize(5, 48);
|
|
|
|
// snd_playSoundEffect(0x6C);
|
|
|
|
for (int i = 123; i <= 138; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
_brandonStatusBit |= 2;
|
|
|
|
if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
|
|
|
|
setTimerCountdown(14, 18000);
|
|
|
|
} else {
|
|
|
|
setTimerCountdown(14, 7200);
|
|
|
|
}
|
|
|
|
_brandonDrawFrame = 113;
|
|
|
|
_brandonStatusBit0x02Flag = 1;
|
|
|
|
_currentCharacter->currentAnimFrame = 113;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) {
|
|
|
|
_screen->fadeSpecialPalette(30, 234, 13, 4);
|
|
|
|
} else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186) {
|
|
|
|
_screen->fadeSpecialPalette(14, 228, 15, 4);
|
|
|
|
}
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::seq_dispelMagicAnimation() {
|
|
|
|
debug(9, "seq_dispelMagicAnimation()");
|
|
|
|
if (_deathHandler == 8)
|
|
|
|
return;
|
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
//if (_unkSceneVar == 4 || _unkSceneVar == 6)
|
|
|
|
// return;
|
|
|
|
}
|
|
|
|
_screen->hideMouse();
|
|
|
|
if (_currentCharacter->sceneId == 210 && _currentCharacter->sceneId < 160)
|
|
|
|
_currentCharacter->facing = 3;
|
|
|
|
// XXX
|
|
|
|
checkAmuletAnimFlags();
|
|
|
|
setGameFlag(0xEE);
|
|
|
|
assert(_magicAnimationTable);
|
|
|
|
setupShapes123(_magicAnimationTable, 5, 0);
|
|
|
|
setBrandonAnimSeqSize(8, 49);
|
|
|
|
// snd_playSoundEffect(0x15);
|
|
|
|
for (int i = 123; i <= 127; ++i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
delayWithTicks(120);
|
|
|
|
|
|
|
|
for (int i = 127; i >= 123; --i) {
|
|
|
|
_currentCharacter->currentAnimFrame = i;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
delayWithTicks(10);
|
|
|
|
}
|
|
|
|
resetBrandonAnimSeqSize();
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
freeShapes123();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
bool KyraEngine::seq_skipSequence() const {
|
2005-08-31 20:14:20 +00:00
|
|
|
debug(9, "KyraEngine::seq_skipSequence()");
|
2005-10-03 20:21:18 +00:00
|
|
|
return _quitFlag || _abortIntroFlag;
|
2005-08-19 22:12:09 +00:00
|
|
|
}
|
|
|
|
|
2005-09-11 14:35:34 +00:00
|
|
|
void KyraEngine::snd_playTheme(int file, int track) {
|
|
|
|
debug(9, "KyraEngine::snd_playTheme(%d)", file);
|
|
|
|
assert(file < _xmidiFilesCount);
|
2005-10-29 18:37:40 +00:00
|
|
|
_curMusicTheme = _newMusicTheme = file;
|
2005-09-11 17:23:04 +00:00
|
|
|
_midi->playMusic(_xmidiFiles[file]);
|
2005-09-11 14:35:34 +00:00
|
|
|
_midi->playTrack(track, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::snd_playTrack(int track) {
|
|
|
|
debug(9, "KyraEngine::snd_playTrack(%d)", track);
|
|
|
|
_midi->playTrack(track, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::snd_setSoundEffectFile(int file) {
|
|
|
|
debug(9, "KyraEngine::snd_setSoundEffectFile(%d)", file);
|
|
|
|
assert(file < _xmidiFilesCount);
|
|
|
|
_midi->loadSoundEffectFile(_xmidiFiles[file]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::snd_playSoundEffect(int track) {
|
|
|
|
debug(9, "KyraEngine::snd_playSoundEffect(%d)", track);
|
|
|
|
_midi->playSoundEffect(track);
|
|
|
|
}
|
|
|
|
|
2005-10-12 19:15:32 +00:00
|
|
|
void KyraEngine::snd_playVoiceFile(int id) {
|
|
|
|
debug(9, "KyraEngine::snd_playVoiceFile(%d)", id);
|
2005-12-12 19:22:49 +00:00
|
|
|
char vocFile[9];
|
2005-12-12 17:39:01 +00:00
|
|
|
assert(id >= 0 && id < 9999);
|
2005-10-15 06:26:53 +00:00
|
|
|
sprintf(vocFile, "%03d.VOC", id);
|
2005-10-12 19:15:32 +00:00
|
|
|
uint32 fileSize = 0;
|
|
|
|
byte *fileData = 0;
|
|
|
|
fileData = _res->fileData(vocFile, &fileSize);
|
|
|
|
assert(fileData);
|
|
|
|
Common::MemoryReadStream vocStream(fileData, fileSize);
|
|
|
|
_mixer->stopHandle(_vocHandle);
|
|
|
|
_currentVocFile = makeVOCStream(vocStream);
|
|
|
|
if (_currentVocFile)
|
|
|
|
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandle, _currentVocFile);
|
|
|
|
delete fileData;
|
|
|
|
fileSize = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KyraEngine::snd_voicePlaying() {
|
|
|
|
return _mixer->isSoundHandleActive(_vocHandle);
|
|
|
|
}
|
|
|
|
|
2005-09-11 14:35:34 +00:00
|
|
|
void KyraEngine::snd_startTrack() {
|
|
|
|
debug(9, "KyraEngine::snd_startTrack()");
|
|
|
|
_midi->startTrack();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::snd_haltTrack() {
|
|
|
|
debug(9, "KyraEngine::snd_haltTrack()");
|
|
|
|
_midi->haltTrack();
|
|
|
|
}
|
|
|
|
|
2005-10-22 00:24:07 +00:00
|
|
|
void KyraEngine::loadMouseShapes() {
|
|
|
|
loadBitmap("MOUSE.CPS", 3, 3, 0);
|
|
|
|
_screen->_curPage = 2;
|
2005-10-29 18:37:40 +00:00
|
|
|
_shapes[4] = _screen->encodeShape(0, 0, 8, 10, 0);
|
|
|
|
_shapes[5] = _screen->encodeShape(0, 0x17, 0x20, 7, 0);
|
|
|
|
_shapes[6] = _screen->encodeShape(0x50, 0x12, 0x10, 9, 0);
|
|
|
|
_shapes[7] = _screen->encodeShape(0x60, 0x12, 0x10, 11, 0);
|
|
|
|
_shapes[8] = _screen->encodeShape(0x70, 0x12, 0x10, 9, 0);
|
|
|
|
_shapes[9] = _screen->encodeShape(0x80, 0x12, 0x10, 11, 0);
|
|
|
|
_shapes[10] = _screen->encodeShape(0x90, 0x12, 0x10, 10, 0);
|
|
|
|
_shapes[364] = _screen->encodeShape(0x28, 0, 0x10, 13, 0);
|
2005-10-22 00:24:07 +00:00
|
|
|
_screen->setMouseCursor(1, 1, 0);
|
2005-10-29 18:37:40 +00:00
|
|
|
_screen->setMouseCursor(1, 1, _shapes[4]);
|
2005-11-01 14:19:50 +00:00
|
|
|
_screen->setShapePages(5, 3);
|
2005-10-22 00:24:07 +00:00
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
void KyraEngine::loadCharacterShapes() {
|
|
|
|
int curImage = 0xFF;
|
|
|
|
int videoPage = _screen->_curPage;
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
for (int i = 0; i < 115; ++i) {
|
|
|
|
assert(i < _defaultShapeTableSize);
|
|
|
|
Shape *shape = &_defaultShapeTable[i];
|
|
|
|
if (shape->imageIndex == 0xFF) {
|
2005-10-30 19:58:51 +00:00
|
|
|
_shapes[i+7+4] = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (shape->imageIndex != curImage) {
|
|
|
|
assert(shape->imageIndex < _characterImageTableSize);
|
|
|
|
loadBitmap(_characterImageTable[shape->imageIndex], 3, 3, 0);
|
|
|
|
curImage = shape->imageIndex;
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
_shapes[i+7+4] = _screen->encodeShape(shape->x<<3, shape->y, shape->w<<3, shape->h, 1);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
_screen->_curPage = videoPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::loadSpecialEffectShapes() {
|
|
|
|
loadBitmap("EFFECTS.CPS", 3, 3, 0);
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
|
|
|
|
int currShape;
|
|
|
|
for (currShape = 173; currShape < 183; currShape++)
|
|
|
|
_shapes[4 + currShape] = _screen->encodeShape((currShape-173) * 24, 0, 24, 24, 1);
|
|
|
|
|
|
|
|
for (currShape = 183; currShape < 190; currShape++)
|
|
|
|
_shapes[4 + currShape] = _screen->encodeShape((currShape-183) * 24, 24, 24, 24, 1);
|
|
|
|
|
|
|
|
for (currShape = 190; currShape < 201; currShape++)
|
|
|
|
_shapes[4 + currShape] = _screen->encodeShape((currShape-190) * 24, 48, 24, 24, 1);
|
|
|
|
|
|
|
|
for (currShape = 201; currShape < 206; currShape++)
|
|
|
|
_shapes[4 + currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::findDuplicateItemShape(int shape) {
|
|
|
|
static uint8 dupTable[] = {
|
|
|
|
0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47,
|
|
|
|
0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a,
|
|
|
|
0x5d, 0x5a, 0x5e, 0x5a, 0xFF, 0xFF
|
|
|
|
};
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
while (dupTable[i] != 0xFF) {
|
|
|
|
if (dupTable[i] == shape)
|
|
|
|
return dupTable[i+1];
|
|
|
|
i += 2;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::loadItems() {
|
|
|
|
int shape;
|
|
|
|
|
|
|
|
loadBitmap("JEWELS3.CPS", 3, 3, 0);
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
|
|
|
|
_shapes[327] = 0;
|
|
|
|
|
|
|
|
for (shape = 1; shape < 6; shape++ )
|
|
|
|
_shapes[327 + shape] = _screen->encodeShape((shape - 1) * 32, 0, 32, 17, 0);
|
|
|
|
|
|
|
|
for (shape = 330; shape <= 334; shape++)
|
|
|
|
_shapes[4 + shape] = _screen->encodeShape((shape-330) * 32, 102, 32, 17, 0);
|
|
|
|
|
|
|
|
for (shape = 335; shape <= 339; shape++)
|
|
|
|
_shapes[4 + shape] = _screen->encodeShape((shape-335) * 32, 17, 32, 17, 0);
|
|
|
|
|
|
|
|
for (shape = 340; shape <= 344; shape++)
|
|
|
|
_shapes[4 + shape] = _screen->encodeShape((shape-340) * 32, 34, 32, 17, 0);
|
|
|
|
|
|
|
|
for (shape = 345; shape <= 349; shape++)
|
|
|
|
_shapes[4 + shape] = _screen->encodeShape((shape-345) * 32, 51, 32, 17, 0);
|
|
|
|
|
|
|
|
for (shape = 350; shape <= 354; shape++)
|
|
|
|
_shapes[4 + shape] = _screen->encodeShape((shape-350) * 32, 68, 32, 17, 0);
|
|
|
|
|
|
|
|
for (shape = 355; shape <= 359; shape++)
|
|
|
|
_shapes[4 + shape] = _screen->encodeShape((shape-355) * 32, 85, 32, 17, 0);
|
|
|
|
|
|
|
|
|
|
|
|
loadBitmap("ITEMS.CPS", 3, 3, 0);
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
|
|
|
|
for (int i = 0; i < 107; i++) {
|
|
|
|
shape = findDuplicateItemShape(i);
|
|
|
|
|
|
|
|
if (shape != -1)
|
|
|
|
_shapes[220 + i] = _shapes[220 + shape];
|
|
|
|
else
|
|
|
|
_shapes[220 + i] = _screen->encodeShape( (i % 20) * 16, i/20 * 16, 16, 16, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 size;
|
|
|
|
uint8 *fileData = _res->fileData("_ITEM_HT.DAT", &size);
|
|
|
|
assert(fileData);
|
|
|
|
|
|
|
|
for (int i = 0; i < 107; i++) {
|
|
|
|
_itemTable[i].height = fileData[i];
|
|
|
|
_itemTable[i].unk1 = _itemTable[i].unk2 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] fileData;
|
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
void KyraEngine::loadButtonShapes() {
|
|
|
|
loadBitmap("BUTTONS2.CPS", 3, 3, 0);
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
_buttonShape0 = _screen->encodeShape(0, 0, 24, 14, 1);
|
|
|
|
_buttonShape1 = _screen->encodeShape(24, 0, 24, 14, 1);
|
|
|
|
_buttonShape2 = _screen->encodeShape(48, 0, 24, 14, 1);
|
|
|
|
_buttonShape3 = _screen->encodeShape(0, 15, 24, 14, 1);
|
|
|
|
_buttonShape4 = _screen->encodeShape(24, 15, 24, 14, 1);
|
|
|
|
_buttonShape5 = _screen->encodeShape(48, 15, 24, 14, 1);
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::initMainButtonList() {
|
|
|
|
_buttonList = &_buttonData[0];
|
|
|
|
for (int i = 0; _buttonDataListPtr[i]; ++i) {
|
|
|
|
_buttonList = initButton(_buttonList, _buttonDataListPtr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
void KyraEngine::loadMainScreen() {
|
|
|
|
if ((_features & GF_ENGLISH) && (_features & GF_TALKIE))
|
|
|
|
loadBitmap("MAIN_ENG.CPS", 3, 3, 0);
|
|
|
|
else if(_features & GF_FRENCH)
|
|
|
|
loadBitmap("MAIN_FRE.CPS", 3, 3, 0);
|
|
|
|
else if(_features & GF_GERMAN)
|
|
|
|
loadBitmap("MAIN_GER.CPS", 3, 3, 0);
|
|
|
|
else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY))
|
|
|
|
loadBitmap("MAIN15.CPS", 3, 3, 0);
|
|
|
|
else if (_features & GF_SPANISH)
|
|
|
|
loadBitmap("MAIN_SPA.CPS", 3, 3, 0);
|
|
|
|
else
|
|
|
|
warning("no main graphics file found");
|
|
|
|
|
|
|
|
uint8 *_page3 = _screen->getPagePtr(3);
|
|
|
|
uint8 *_page0 = _screen->getPagePtr(0);
|
|
|
|
memcpy(_page0, _page3, 320*200);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setCharactersInDefaultScene() {
|
|
|
|
static uint32 defaultSceneTable[][4] = {
|
|
|
|
{ 0xFFFF, 0x0004, 0x0003, 0xFFFF },
|
|
|
|
{ 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
|
|
|
|
{ 0xFFFF, 0x001D, 0x0021, 0xFFFF },
|
|
|
|
{ 0xFFFF, 0x0000, 0x0000, 0xFFFF }
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 1; i < 5; ++i) {
|
|
|
|
Character *cur = &_characterList[i];
|
|
|
|
cur->field_20 = 0;
|
|
|
|
uint32 *curTable = defaultSceneTable[i-1];
|
|
|
|
cur->sceneId = curTable[0];
|
|
|
|
if (cur->sceneId == _currentCharacter->sceneId) {
|
|
|
|
++cur->field_20;
|
|
|
|
cur->sceneId = curTable[cur->field_20];
|
|
|
|
}
|
|
|
|
cur->field_23 = curTable[cur->field_20+1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setCharacterDefaultFrame(int character) {
|
|
|
|
static uint16 initFrameTable[] = {
|
2005-11-01 14:19:50 +00:00
|
|
|
7, 41, 77, 0, 0
|
2005-10-29 18:37:40 +00:00
|
|
|
};
|
|
|
|
assert(character < ARRAYSIZE(initFrameTable));
|
|
|
|
Character *edit = &_characterList[character];
|
|
|
|
edit->sceneId = 0xFFFF;
|
|
|
|
edit->facing = 0;
|
|
|
|
edit->currentAnimFrame = initFrameTable[character];
|
|
|
|
edit->unk6 = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setCharactersPositions(int character) {
|
2005-11-01 14:19:50 +00:00
|
|
|
static uint16 initXPosTable[] = {
|
2005-10-29 18:37:40 +00:00
|
|
|
0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
|
2005-11-01 14:19:50 +00:00
|
|
|
0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
|
2005-10-29 18:37:40 +00:00
|
|
|
};
|
2005-11-01 14:19:50 +00:00
|
|
|
static uint8 initYPosTable[] = {
|
2005-10-29 18:37:40 +00:00
|
|
|
0x00, 0xA2, 0x00, 0x42, 0x00,
|
|
|
|
0x67, 0x67, 0x60, 0x5A, 0x71,
|
|
|
|
0x76
|
|
|
|
};
|
|
|
|
assert(character < ARRAYSIZE(initXPosTable));
|
|
|
|
Character *edit = &_characterList[character];
|
|
|
|
edit->x1 = edit->x2 = initXPosTable[character];
|
|
|
|
edit->y1 = edit->y2 = initYPosTable[character];
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setCharactersHeight() {
|
|
|
|
static int8 initHeightTable[] = {
|
2005-11-01 14:19:50 +00:00
|
|
|
48, 40, 48, 47, 56,
|
|
|
|
44, 42, 47, 38, 35,
|
|
|
|
40
|
2005-10-29 18:37:40 +00:00
|
|
|
};
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
_characterList[i].height = initHeightTable[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::setGameFlag(int flag) {
|
|
|
|
_flagsTable[flag >> 3] |= (1 << (flag & 7));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::queryGameFlag(int flag) {
|
|
|
|
return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::resetGameFlag(int flag) {
|
|
|
|
_flagsTable[flag >> 3] &= ~(1 << (flag & 7));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive);
|
2005-10-29 18:37:40 +00:00
|
|
|
int unkVar1 = 1;
|
|
|
|
_screen->hideMouse();
|
2005-12-24 18:00:35 +00:00
|
|
|
_handleInput = false;
|
|
|
|
_abortWalkFlag = false;
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = false;
|
2005-10-29 18:37:40 +00:00
|
|
|
if (_currentCharacter->sceneId == 7 && sceneId == 24) {
|
|
|
|
_newMusicTheme = 2;
|
|
|
|
} else if (_currentCharacter->sceneId == 25 && sceneId == 109) {
|
|
|
|
_newMusicTheme = 3;
|
|
|
|
} else if (_currentCharacter->sceneId == 120 && sceneId == 37) {
|
|
|
|
_newMusicTheme = 4;
|
|
|
|
} else if (_currentCharacter->sceneId == 52 && sceneId == 199) {
|
|
|
|
_newMusicTheme = 5;
|
|
|
|
} else if (_currentCharacter->sceneId == 37 && sceneId == 120) {
|
|
|
|
_newMusicTheme = 3;
|
|
|
|
} else if (_currentCharacter->sceneId == 109 && sceneId == 25) {
|
|
|
|
_newMusicTheme = 2;
|
|
|
|
} else if (_currentCharacter->sceneId == 24 && sceneId == 7) {
|
|
|
|
_newMusicTheme = 1;
|
|
|
|
}
|
|
|
|
if (_newMusicTheme != _curMusicTheme) {
|
|
|
|
snd_playTheme(_newMusicTheme);
|
|
|
|
}
|
2005-11-13 19:35:01 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
switch (_currentCharacter->sceneId) {
|
|
|
|
case 1:
|
|
|
|
if (sceneId == 0) {
|
|
|
|
moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
|
|
|
|
unkVar1 = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
if (sceneId == 2) {
|
|
|
|
moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
|
|
|
|
unkVar1 = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 26:
|
|
|
|
if (sceneId == 27) {
|
|
|
|
moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
|
|
|
|
unkVar1 = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 44:
|
|
|
|
if (sceneId == 45) {
|
|
|
|
moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
|
|
|
|
unkVar1 = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unkVar1 && unk1) {
|
|
|
|
int xpos = _currentCharacter->x1;
|
|
|
|
int ypos = _currentCharacter->y1;
|
|
|
|
switch (facing) {
|
|
|
|
case 0:
|
|
|
|
ypos = _currentCharacter->y1 - 6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
xpos = 336;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
ypos = 143;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
xpos = -16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
moveCharacterToPos(0, facing, xpos, ypos);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
wsa_close(_wsaObjects[i]);
|
|
|
|
_wsaObjects[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!brandonAlive) {
|
|
|
|
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
|
|
|
|
_scriptInterpreter->startScript(_scriptClick, 5);
|
|
|
|
while (_scriptInterpreter->validScript(_scriptClick)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4);
|
|
|
|
_currentCharacter->sceneId = sceneId;
|
|
|
|
|
|
|
|
assert(sceneId < _roomTableSize);
|
2005-12-09 14:52:31 +00:00
|
|
|
assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
2005-11-27 10:02:23 +00:00
|
|
|
|
|
|
|
if (_currentRoom != 0xFFFF && (_features & GF_TALKIE)) {
|
|
|
|
char file[32];
|
|
|
|
assert(_currentRoom < _roomTableSize);
|
|
|
|
int tableId = _roomTable[_currentRoom].nameIndex;
|
|
|
|
assert(tableId < _roomFilenameTableSize);
|
|
|
|
strcpy(file, _roomFilenameTable[tableId]);
|
|
|
|
strcat(file, ".VRM");
|
|
|
|
_res->unloadPakFile(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
_currentRoom = sceneId;
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
|
2005-11-27 10:02:23 +00:00
|
|
|
char fileNameBuffer[32];
|
|
|
|
strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
|
|
|
|
strcat(fileNameBuffer, ".DAT");
|
|
|
|
_sprites->loadDAT(fileNameBuffer, _sceneExits);
|
2005-11-10 14:08:50 +00:00
|
|
|
_sprites->setupSceneAnims();
|
2005-11-09 22:26:12 +00:00
|
|
|
_scriptInterpreter->unloadScript(_scriptClickData);
|
2005-10-29 18:37:40 +00:00
|
|
|
loadSceneMSC();
|
|
|
|
|
2005-11-27 10:02:23 +00:00
|
|
|
if ((_features & GF_TALKIE)) {
|
|
|
|
strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
|
|
|
|
strcat(fileNameBuffer, ".VRM");
|
|
|
|
_res->loadPakFile(fileNameBuffer);
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
_walkBlockNorth = currentRoom->northExit;
|
|
|
|
_walkBlockEast = currentRoom->eastExit;
|
|
|
|
_walkBlockSouth = currentRoom->southExit;
|
|
|
|
_walkBlockWest = currentRoom->westExit;
|
|
|
|
|
|
|
|
if (_walkBlockNorth == 0xFFFF) {
|
|
|
|
blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3);
|
|
|
|
}
|
|
|
|
if (_walkBlockEast == 0xFFFF) {
|
|
|
|
blockOutRegion(312, 0, 8, 139);
|
|
|
|
}
|
|
|
|
if (_walkBlockSouth == 0xFFFF) {
|
|
|
|
blockOutRegion(0, 135, 320, 8);
|
|
|
|
}
|
|
|
|
if (_walkBlockWest == 0xFFFF) {
|
|
|
|
blockOutRegion(0, 0, 8, 139);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!brandonAlive) {
|
2005-12-23 17:49:14 +00:00
|
|
|
updatePlayerItemsForScene();
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
2005-12-09 14:52:31 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
startSceneScript(brandonAlive);
|
2005-12-08 17:19:18 +00:00
|
|
|
setupSceneItems();
|
2005-12-09 14:52:31 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
initSceneData(facing, unk2, brandonAlive);
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
_loopFlag2 = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
_screen->showMouse();
|
|
|
|
if (!brandonAlive) {
|
2005-12-28 21:34:40 +00:00
|
|
|
seq_poisonDeathNow(0);
|
2005-12-24 18:00:35 +00:00
|
|
|
}
|
2005-12-13 15:10:20 +00:00
|
|
|
updateMousePointer(true);
|
2005-12-24 18:00:35 +00:00
|
|
|
_changedScene = true;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-12-09 23:02:16 +00:00
|
|
|
void KyraEngine::transcendScenes(int roomIndex, int roomName) {
|
2005-12-22 19:31:38 +00:00
|
|
|
debug(9, "transcendScenes(%d, %d)", roomIndex, roomName);
|
2005-12-09 23:02:16 +00:00
|
|
|
assert(roomIndex < _roomTableSize);
|
2005-12-13 13:27:58 +00:00
|
|
|
if (_features & GF_TALKIE) {
|
|
|
|
char file[32];
|
|
|
|
assert(roomIndex < _roomTableSize);
|
|
|
|
int tableId = _roomTable[roomIndex].nameIndex;
|
|
|
|
assert(tableId < _roomFilenameTableSize);
|
|
|
|
strcpy(file, _roomFilenameTable[tableId]);
|
|
|
|
strcat(file, ".VRM");
|
|
|
|
_res->unloadPakFile(file);
|
|
|
|
}
|
2005-12-09 23:02:16 +00:00
|
|
|
_roomTable[roomIndex].nameIndex = roomName;
|
2005-12-13 16:56:33 +00:00
|
|
|
_unkScreenVar2 = 1;
|
|
|
|
_unkScreenVar3 = 1;
|
|
|
|
_unkScreenVar1 = 0;
|
2005-12-09 23:02:16 +00:00
|
|
|
_brandonPosX = _currentCharacter->x1;
|
|
|
|
_brandonPosY = _currentCharacter->y1;
|
|
|
|
enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
|
2005-12-13 16:56:33 +00:00
|
|
|
_unkScreenVar1 = 1;
|
|
|
|
_unkScreenVar2 = 0;
|
|
|
|
_unkScreenVar3 = 0;
|
2005-12-09 23:02:16 +00:00
|
|
|
}
|
|
|
|
|
2005-12-22 19:31:38 +00:00
|
|
|
void KyraEngine::setSceneFile(int roomIndex, int roomName) {
|
|
|
|
debug(9, "setSceneFile(%d, %d)", roomIndex, roomName);
|
|
|
|
assert(roomIndex < _roomTableSize);
|
|
|
|
_roomTable[roomIndex].nameIndex = roomName;
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
|
|
|
|
debug(9, "moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos);
|
|
|
|
Character *ch = &_characterList[character];
|
2005-11-13 19:35:01 +00:00
|
|
|
ch->facing = facing;
|
2005-10-29 18:37:40 +00:00
|
|
|
_screen->hideMouse();
|
2005-12-09 23:02:16 +00:00
|
|
|
xpos = (int16)(xpos & 0xFFFC);
|
|
|
|
ypos = (int16)(ypos & 0xFFFE);
|
2005-11-13 19:35:01 +00:00
|
|
|
disableTimer(19);
|
|
|
|
disableTimer(14);
|
|
|
|
disableTimer(18);
|
2005-11-18 23:55:31 +00:00
|
|
|
uint32 nextFrame = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
switch (facing) {
|
|
|
|
case 0:
|
2005-11-13 19:35:01 +00:00
|
|
|
while (ypos < ch->y1) {
|
2005-11-18 23:55:31 +00:00
|
|
|
nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
|
2005-10-29 18:37:40 +00:00
|
|
|
setCharacterPositionWithUpdate(character);
|
2005-11-18 23:55:31 +00:00
|
|
|
while (_system->getMillis() < nextFrame) { updateGameTimers(); }
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2005-11-13 19:35:01 +00:00
|
|
|
while (ch->x1 < xpos) {
|
2005-11-18 23:55:31 +00:00
|
|
|
nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
|
2005-10-29 18:37:40 +00:00
|
|
|
setCharacterPositionWithUpdate(character);
|
2005-11-18 23:55:31 +00:00
|
|
|
while (_system->getMillis() < nextFrame) { updateGameTimers(); }
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
2005-11-13 19:35:01 +00:00
|
|
|
while (ypos > ch->y1) {
|
2005-11-18 23:55:31 +00:00
|
|
|
nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
|
2005-10-29 18:37:40 +00:00
|
|
|
setCharacterPositionWithUpdate(character);
|
2005-11-18 23:55:31 +00:00
|
|
|
while (_system->getMillis() < nextFrame) { updateGameTimers(); }
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
2005-11-13 19:35:01 +00:00
|
|
|
while (ch->x1 > xpos) {
|
2005-11-18 23:55:31 +00:00
|
|
|
nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
|
2005-10-29 18:37:40 +00:00
|
|
|
setCharacterPositionWithUpdate(character);
|
2005-11-18 23:55:31 +00:00
|
|
|
while (_system->getMillis() < nextFrame) { updateGameTimers(); }
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-11-13 19:35:01 +00:00
|
|
|
enableTimer(19);
|
|
|
|
enableTimer(14);
|
|
|
|
enableTimer(18);
|
2005-10-29 18:37:40 +00:00
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setCharacterPositionWithUpdate(int character) {
|
|
|
|
debug(9, "setCharacterPositionWithUpdate(%d)", character);
|
|
|
|
setCharacterPosition(character, 0);
|
2005-11-13 19:35:01 +00:00
|
|
|
_sprites->updateSceneAnims();
|
|
|
|
updateGameTimers();
|
2005-10-29 18:37:40 +00:00
|
|
|
updateAllObjectShapes();
|
2005-12-09 14:52:31 +00:00
|
|
|
updateTextFade();
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
// XXX game_updateKyragemFading
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
int KyraEngine::setCharacterPosition(int character, int *facingTable) {
|
|
|
|
debug(9, "setCharacterPosition(%d, 0x%X)", character, facingTable);
|
2005-10-29 18:37:40 +00:00
|
|
|
if (character == 0) {
|
2005-11-01 14:19:50 +00:00
|
|
|
_currentCharacter->x1 += _charXPosTable[_currentCharacter->facing];
|
|
|
|
_currentCharacter->y1 += _charYPosTable[_currentCharacter->facing];
|
2005-11-09 22:26:12 +00:00
|
|
|
setCharacterPositionHelper(0, facingTable);
|
2005-11-01 14:19:50 +00:00
|
|
|
return 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
} else {
|
2005-11-09 22:26:12 +00:00
|
|
|
_characterList[character].x1 += _charXPosTable[_characterList[character].facing];
|
|
|
|
_characterList[character].y1 += _charYPosTable[_characterList[character].facing];
|
2005-10-29 18:37:40 +00:00
|
|
|
if (_characterList[character].sceneId == _currentCharacter->sceneId) {
|
|
|
|
setCharacterPositionHelper(character, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
void KyraEngine::setCharacterPositionHelper(int character, int *facingTable) {
|
|
|
|
debug(9, "setCharacterPositionHelper(%d, 0x%X)", character, facingTable);
|
2005-10-29 18:37:40 +00:00
|
|
|
Character *ch = &_characterList[character];
|
2005-11-01 14:19:50 +00:00
|
|
|
++ch->currentAnimFrame;
|
2005-10-29 18:37:40 +00:00
|
|
|
int facing = ch->facing;
|
2005-11-09 22:26:12 +00:00
|
|
|
if (facingTable) {
|
|
|
|
if (*facingTable != *(facingTable - 1)) {
|
|
|
|
if (*(facingTable - 1) == *(facingTable + 1)) {
|
|
|
|
facing = getOppositeFacingDirection(*(facingTable - 1));
|
|
|
|
*facingTable = *(facingTable - 1);
|
|
|
|
}
|
|
|
|
}
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-11-01 14:19:50 +00:00
|
|
|
static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
if (facing == 0) {
|
|
|
|
++facingIsZero[character];
|
|
|
|
} else {
|
|
|
|
bool resetTables = false;
|
|
|
|
if (facing != 7) {
|
|
|
|
if (facing - 1 != 0) {
|
|
|
|
if (facing != 4) {
|
|
|
|
if (facing == 3 || facing == 5) {
|
2005-11-26 16:37:20 +00:00
|
|
|
if (facingIsFour[character] > 2) {
|
2005-10-29 18:37:40 +00:00
|
|
|
facing = 4;
|
|
|
|
}
|
|
|
|
resetTables = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
++facingIsFour[character];
|
|
|
|
}
|
|
|
|
} else {
|
2005-11-09 22:26:12 +00:00
|
|
|
if (facingIsZero[character] > 2) {
|
2005-10-29 18:37:40 +00:00
|
|
|
facing = 0;
|
|
|
|
}
|
|
|
|
resetTables = true;
|
|
|
|
}
|
2005-11-26 16:37:20 +00:00
|
|
|
} else {
|
|
|
|
if (facingIsZero[character] > 2) {
|
|
|
|
facing = 0;
|
|
|
|
}
|
|
|
|
resetTables = true;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (resetTables) {
|
|
|
|
facingIsZero[character] = 0;
|
|
|
|
facingIsFour[character] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
static const uint16 maxAnimationFrame[] = {
|
2005-10-29 18:37:40 +00:00
|
|
|
0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
|
|
|
|
0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
|
|
|
|
0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
|
|
|
|
0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
|
|
|
|
0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
|
|
|
|
0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
|
|
|
|
0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
|
|
|
|
};
|
|
|
|
|
|
|
|
if (facing == 0) {
|
2005-11-13 19:35:01 +00:00
|
|
|
if (maxAnimationFrame[36+character] > ch->currentAnimFrame) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ch->currentAnimFrame = maxAnimationFrame[36+character];
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
if (maxAnimationFrame[30+character] < ch->currentAnimFrame) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ch->currentAnimFrame = maxAnimationFrame[36+character];
|
|
|
|
}
|
|
|
|
} else if (facing == 4) {
|
2005-11-13 19:35:01 +00:00
|
|
|
if (maxAnimationFrame[18+character] > ch->currentAnimFrame) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ch->currentAnimFrame = maxAnimationFrame[18+character];
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
if (maxAnimationFrame[12+character] < ch->currentAnimFrame) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ch->currentAnimFrame = maxAnimationFrame[18+character];
|
|
|
|
}
|
|
|
|
} else {
|
2005-11-09 22:26:12 +00:00
|
|
|
if (maxAnimationFrame[18+character] < ch->currentAnimFrame) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ch->currentAnimFrame = maxAnimationFrame[30+character];
|
|
|
|
}
|
|
|
|
if (maxAnimationFrame[character] == ch->currentAnimFrame) {
|
|
|
|
ch->currentAnimFrame = maxAnimationFrame[6+character];
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
if (maxAnimationFrame[character] < ch->currentAnimFrame) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ch->currentAnimFrame = maxAnimationFrame[6+character]+2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (character == 0) {
|
|
|
|
if (_brandonStatusBit & 0x10)
|
|
|
|
ch->currentAnimFrame = 88;
|
|
|
|
}
|
|
|
|
|
|
|
|
animRefreshNPC(character);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::getOppositeFacingDirection(int dir) {
|
2005-11-13 19:35:01 +00:00
|
|
|
debug(9, "getOppositeFacingDirection(%d)", dir);
|
2005-10-29 18:37:40 +00:00
|
|
|
switch (dir) {
|
|
|
|
case 0:
|
|
|
|
return 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
return 7;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
return 6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
return 5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
return 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
return 3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::loadSceneMSC() {
|
|
|
|
assert(_currentCharacter->sceneId < _roomTableSize);
|
|
|
|
int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
|
|
|
|
assert(tableId < _roomFilenameTableSize);
|
|
|
|
char fileNameBuffer[32];
|
|
|
|
strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
|
|
|
|
strcat(fileNameBuffer, ".MSC");
|
2005-11-13 19:35:01 +00:00
|
|
|
_screen->fillRect(0, 0, 319, 199, 0, 5);
|
2005-10-29 18:37:40 +00:00
|
|
|
loadBitmap(fileNameBuffer, 3, 5, 0);
|
|
|
|
}
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
// maybe move these two functions to Screen
|
2005-10-29 18:37:40 +00:00
|
|
|
void KyraEngine::blockInRegion(int x, int y, int width, int height) {
|
2005-11-10 21:42:42 +00:00
|
|
|
debug(9, "blockInRegion(%d, %d, %d, %d)", x, y, width, height);
|
2005-10-29 18:37:40 +00:00
|
|
|
assert(_screen->_shapePages[0]);
|
|
|
|
byte *toPtr = _screen->_shapePages[0] + (y * 320 + x);
|
|
|
|
for (int i = 0; i < height; ++i) {
|
|
|
|
byte *backUpTo = toPtr;
|
|
|
|
for (int i2 = 0; i2 < width; ++i2) {
|
|
|
|
*toPtr++ &= 0x7F;
|
|
|
|
}
|
|
|
|
toPtr = (backUpTo + 320);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::blockOutRegion(int x, int y, int width, int height) {
|
2005-11-10 21:42:42 +00:00
|
|
|
debug(9, "blockOutRegion(%d, %d, %d, %d)", x, y, width, height);
|
2005-10-29 18:37:40 +00:00
|
|
|
assert(_screen->_shapePages[0]);
|
|
|
|
byte *toPtr = _screen->_shapePages[0] + (y * 320 + x);
|
|
|
|
for (int i = 0; i < height; ++i) {
|
|
|
|
byte *backUpTo = toPtr;
|
|
|
|
for (int i2 = 0; i2 < width; ++i2) {
|
|
|
|
*toPtr++ |= 0x80;
|
|
|
|
}
|
|
|
|
toPtr = (backUpTo + 320);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::startSceneScript(int brandonAlive) {
|
|
|
|
debug(9, "startSceneScript(%d)", brandonAlive);
|
|
|
|
assert(_currentCharacter->sceneId < _roomTableSize);
|
|
|
|
int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
|
|
|
|
assert(tableId < _roomFilenameTableSize);
|
|
|
|
char fileNameBuffer[32];
|
|
|
|
strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
|
|
|
|
strcat(fileNameBuffer, ".CPS");
|
|
|
|
loadBitmap(fileNameBuffer, 3, 3, 0);
|
|
|
|
_sprites->loadSceneShapes();
|
2005-11-13 19:35:01 +00:00
|
|
|
_exitListPtr = 0;
|
2005-11-11 22:17:06 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
_screen->setScreenPalette(_screen->_currentPalette);
|
2005-12-13 16:56:33 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
_scaleMode = 1;
|
|
|
|
for (int i = 0; i < 145; ++i) {
|
|
|
|
_scaleTable[i] = 256;
|
|
|
|
}
|
|
|
|
|
|
|
|
clearNoDropRects();
|
|
|
|
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
|
|
|
|
strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
|
|
|
|
strcat(fileNameBuffer, ".EMC");
|
|
|
|
_scriptInterpreter->unloadScript(_scriptClickData);
|
|
|
|
_scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, _opcodeTable, _opcodeTableSize, 0);
|
|
|
|
_scriptInterpreter->startScript(_scriptClick, 0);
|
|
|
|
_scriptClick->variables[0] = _currentCharacter->sceneId;
|
|
|
|
_scriptClick->variables[7] = brandonAlive;
|
|
|
|
|
|
|
|
while (_scriptInterpreter->validScript(_scriptClick)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) {
|
|
|
|
debug(9, "initSceneData(%d, %d, %d)", facing, unk1, brandonAlive);
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
int16 xpos2 = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
int setFacing = 1;
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
int16 xpos = 0, ypos = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
if (_brandonPosX == -1 && _brandonPosY == -1) {
|
2005-11-13 19:35:01 +00:00
|
|
|
switch (facing+1) {
|
2005-10-29 18:37:40 +00:00
|
|
|
case 0:
|
|
|
|
xpos = ypos = -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: case 2: case 8:
|
2005-11-09 22:26:12 +00:00
|
|
|
xpos = _sceneExits.southXPos;
|
|
|
|
ypos = _sceneExits.southYPos;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2005-11-09 22:26:12 +00:00
|
|
|
xpos = _sceneExits.westXPos;
|
|
|
|
ypos = _sceneExits.westYPos;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 4: case 5: case 6:
|
2005-11-09 22:26:12 +00:00
|
|
|
xpos = _sceneExits.northXPos;
|
|
|
|
ypos = _sceneExits.northYPos;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
2005-11-09 22:26:12 +00:00
|
|
|
xpos = _sceneExits.eastXPos;
|
|
|
|
ypos = _sceneExits.eastYPos;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-12-22 19:31:38 +00:00
|
|
|
if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) {
|
|
|
|
ypos = (_northExitHeight & 0xFF) + 4;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
if (xpos >= 308) {
|
|
|
|
xpos = 304;
|
|
|
|
}
|
2005-11-13 19:35:01 +00:00
|
|
|
if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) {
|
2005-10-29 18:37:40 +00:00
|
|
|
ypos = (_northExitHeight >> 8) - 4;
|
|
|
|
}
|
|
|
|
if (xpos <= 12) {
|
|
|
|
xpos = 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_brandonPosX > -1) {
|
|
|
|
xpos = _brandonPosX;
|
|
|
|
}
|
|
|
|
if (_brandonPosY > -1) {
|
|
|
|
ypos = _brandonPosY;
|
|
|
|
}
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
int16 ypos2 = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
if (_brandonPosX > -1 && _brandonPosY > -1) {
|
|
|
|
switch (_currentCharacter->sceneId) {
|
|
|
|
case 1:
|
|
|
|
_currentCharacter->x1 = xpos;
|
|
|
|
_currentCharacter->x2 = xpos;
|
|
|
|
_currentCharacter->y1 = ypos;
|
|
|
|
_currentCharacter->y2 = ypos;
|
|
|
|
facing = 4;
|
|
|
|
xpos2 = 192;
|
|
|
|
ypos2 = 104;
|
2005-11-13 19:35:01 +00:00
|
|
|
setFacing = 0;
|
|
|
|
unk1 = 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
_currentCharacter->x1 = xpos;
|
|
|
|
_currentCharacter->x2 = xpos;
|
|
|
|
_currentCharacter->y1 = ypos;
|
|
|
|
_currentCharacter->y2 = ypos;
|
|
|
|
facing = 2;
|
|
|
|
xpos2 = 204;
|
|
|
|
ypos2 = 94;
|
2005-11-13 19:35:01 +00:00
|
|
|
setFacing = 0;
|
|
|
|
unk1 = 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 26:
|
|
|
|
_currentCharacter->x1 = xpos;
|
|
|
|
_currentCharacter->x2 = xpos;
|
|
|
|
_currentCharacter->y1 = ypos;
|
|
|
|
_currentCharacter->y2 = ypos;
|
2005-12-22 19:31:38 +00:00
|
|
|
facing = 2;
|
2005-10-29 18:37:40 +00:00
|
|
|
xpos2 = 192;
|
|
|
|
ypos2 = 128;
|
2005-11-13 19:35:01 +00:00
|
|
|
setFacing = 0;
|
|
|
|
unk1 = 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 44:
|
|
|
|
_currentCharacter->x1 = xpos;
|
|
|
|
_currentCharacter->x2 = xpos;
|
|
|
|
_currentCharacter->y1 = ypos;
|
|
|
|
_currentCharacter->y2 = ypos;
|
|
|
|
facing = 6;
|
|
|
|
xpos2 = 156;
|
|
|
|
ypos2 = 96;
|
2005-11-13 19:35:01 +00:00
|
|
|
setFacing = 0;
|
|
|
|
unk1 = 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 37:
|
|
|
|
_currentCharacter->x1 = xpos;
|
|
|
|
_currentCharacter->x2 = xpos;
|
|
|
|
_currentCharacter->y1 = ypos;
|
|
|
|
_currentCharacter->y2 = ypos;
|
|
|
|
facing = 2;
|
|
|
|
xpos2 = 148;
|
|
|
|
ypos2 = 114;
|
2005-11-13 19:35:01 +00:00
|
|
|
setFacing = 0;
|
|
|
|
unk1 = 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_brandonPosX = _brandonPosY = -1;
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
if (unk1 && setFacing) {
|
|
|
|
ypos2 = ypos;
|
2005-10-29 18:37:40 +00:00
|
|
|
xpos2 = xpos;
|
|
|
|
switch (facing) {
|
|
|
|
case 0:
|
|
|
|
ypos = 142;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
xpos = -16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
2005-11-13 19:35:01 +00:00
|
|
|
ypos = (uint8)(_northExitHeight & 0xFF) - 4;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
2005-11-13 19:35:01 +00:00
|
|
|
xpos = 336;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 23:02:16 +00:00
|
|
|
xpos2 = (int16)(xpos2 & 0xFFFC);
|
|
|
|
ypos2 = (int16)(ypos2 & 0xFFFE);
|
|
|
|
xpos = (int16)(xpos & 0xFFFC);
|
|
|
|
ypos = (int16)(ypos & 0xFFFE);
|
2005-10-29 18:37:40 +00:00
|
|
|
_currentCharacter->facing = facing;
|
|
|
|
_currentCharacter->x1 = xpos;
|
|
|
|
_currentCharacter->x2 = xpos;
|
|
|
|
_currentCharacter->y1 = ypos;
|
|
|
|
_currentCharacter->y2 = ypos;
|
|
|
|
|
|
|
|
initSceneObjectList(brandonAlive);
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
if (unk1 && brandonAlive == 0) {
|
2005-10-29 18:37:40 +00:00
|
|
|
moveCharacterToPos(0, facing, xpos2, ypos2);
|
|
|
|
}
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
_scriptClick->variables[4] = _itemInHand;
|
2005-10-29 18:37:40 +00:00
|
|
|
_scriptClick->variables[7] = brandonAlive;
|
|
|
|
_scriptInterpreter->startScript(_scriptClick, 3);
|
|
|
|
while (_scriptInterpreter->validScript(_scriptClick)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::resetBrandonPosionFlags() {
|
|
|
|
_brandonStatusBit = 0;
|
|
|
|
for (int i = 0; i < 256; ++i) {
|
2005-12-28 21:34:40 +00:00
|
|
|
_brandonPoisonFlagsGFX[i] = i;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::initAnimStateList() {
|
|
|
|
_animStates[0].index = 0;
|
|
|
|
_animStates[0].active = 1;
|
|
|
|
_animStates[0].flags = 0x800;
|
|
|
|
_animStates[0].background = _shapes[2];
|
|
|
|
_animStates[0].rectSize = _screen->getRectSize(4, 48);
|
|
|
|
_animStates[0].width = 4;
|
|
|
|
_animStates[0].height = 48;
|
|
|
|
_animStates[0].width2 = 4;
|
|
|
|
_animStates[0].height2 = 3;
|
|
|
|
|
|
|
|
for (int i = 1; i <= 4; ++i) {
|
|
|
|
_animStates[i].index = i;
|
|
|
|
_animStates[i].active = 0;
|
|
|
|
_animStates[i].flags = 0x800;
|
|
|
|
_animStates[i].background = _shapes[3];
|
|
|
|
_animStates[i].rectSize = _screen->getRectSize(4, 64);
|
|
|
|
_animStates[i].width = 4;
|
|
|
|
_animStates[i].height = 48;
|
|
|
|
_animStates[i].width2 = 4;
|
|
|
|
_animStates[i].height2 = 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 5; i < 16; ++i) {
|
|
|
|
_animStates[i].index = i;
|
|
|
|
_animStates[i].active = 0;
|
|
|
|
_animStates[i].flags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 16; i < 28; ++i) {
|
|
|
|
_animStates[i].index = i;
|
|
|
|
_animStates[i].flags = 0;
|
|
|
|
_animStates[i].background = _shapes[349+i];
|
|
|
|
_animStates[i].rectSize = _screen->getRectSize(3, 24);
|
|
|
|
_animStates[i].width = 3;
|
|
|
|
_animStates[i].height = 16;
|
|
|
|
_animStates[i].width2 = 0;
|
|
|
|
_animStates[i].height2 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::initSceneObjectList(int brandonAlive) {
|
2005-10-30 19:58:51 +00:00
|
|
|
debug(9, "initSceneObjectList(%d)", brandonAlive);
|
|
|
|
for (int i = 0; i < 31; ++i) {
|
|
|
|
_charactersAnimState[i].active = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int startAnimFrame = 0;
|
|
|
|
|
|
|
|
AnimObject *curAnimState = _charactersAnimState;
|
|
|
|
curAnimState->active = 1;
|
|
|
|
curAnimState->drawY = _currentCharacter->y1;
|
|
|
|
curAnimState->sceneAnimPtr = _shapes[4+_currentCharacter->currentAnimFrame];
|
|
|
|
curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
|
|
|
|
startAnimFrame = _currentCharacter->currentAnimFrame-7;
|
|
|
|
int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
|
|
|
|
int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
|
|
|
|
if (_scaleMode) {
|
|
|
|
curAnimState->x1 = _currentCharacter->x1;
|
|
|
|
curAnimState->y1 = _currentCharacter->y1;
|
|
|
|
|
|
|
|
_brandonScaleX = _scaleTable[_currentCharacter->y1];
|
|
|
|
_brandonScaleY = _scaleTable[_currentCharacter->y1];
|
|
|
|
|
|
|
|
curAnimState->x1 += (_brandonScaleX * xOffset) >> 8;
|
|
|
|
curAnimState->y1 += (_brandonScaleY * yOffset) >> 8;
|
|
|
|
} else {
|
2005-11-09 22:26:12 +00:00
|
|
|
curAnimState->x1 = _currentCharacter->x1 + xOffset;
|
|
|
|
curAnimState->y1 = _currentCharacter->y1 + yOffset;
|
2005-10-30 19:58:51 +00:00
|
|
|
}
|
|
|
|
curAnimState->x2 = curAnimState->x1;
|
|
|
|
curAnimState->y2 = curAnimState->y1;
|
|
|
|
curAnimState->refreshFlag = 1;
|
|
|
|
curAnimState->bkgdChangeFlag = 1;
|
|
|
|
_objectQueue = 0;
|
|
|
|
_objectQueue = objectAddHead(0, curAnimState);
|
|
|
|
|
|
|
|
int listAdded = 0;
|
|
|
|
int addedObjects = 1;
|
|
|
|
|
|
|
|
for (int i = 1; i < 5; ++i) {
|
|
|
|
Character *ch = &_characterList[i];
|
2005-12-20 10:58:07 +00:00
|
|
|
curAnimState = &_charactersAnimState[addedObjects];
|
2005-10-30 19:58:51 +00:00
|
|
|
if (ch->sceneId != _currentCharacter->sceneId) {
|
2005-12-20 10:58:07 +00:00
|
|
|
curAnimState->active = 0;
|
|
|
|
curAnimState->refreshFlag = 0;
|
|
|
|
curAnimState->bkgdChangeFlag = 0;
|
2005-10-30 19:58:51 +00:00
|
|
|
++addedObjects;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
curAnimState->drawY = ch->y1;
|
|
|
|
curAnimState->sceneAnimPtr = _shapes[4+ch->currentAnimFrame];
|
|
|
|
curAnimState->animFrameNumber = ch->currentAnimFrame;
|
|
|
|
startAnimFrame = ch->currentAnimFrame-7;
|
|
|
|
xOffset = _defaultShapeTable[startAnimFrame].xOffset;
|
|
|
|
yOffset = _defaultShapeTable[startAnimFrame].yOffset;
|
|
|
|
if (_scaleMode) {
|
|
|
|
curAnimState->x1 = ch->x1;
|
|
|
|
curAnimState->y1 = ch->y1;
|
|
|
|
|
|
|
|
_brandonScaleX = _scaleTable[ch->y1];
|
|
|
|
_brandonScaleY = _scaleTable[ch->y1];
|
|
|
|
|
|
|
|
curAnimState->x1 += (_brandonScaleX * xOffset) >> 8;
|
|
|
|
curAnimState->y1 += (_brandonScaleY * yOffset) >> 8;
|
|
|
|
} else {
|
2005-11-09 22:26:12 +00:00
|
|
|
curAnimState->x1 = ch->x1 + xOffset;
|
|
|
|
curAnimState->y1 = ch->y1 + yOffset;
|
2005-10-30 19:58:51 +00:00
|
|
|
}
|
|
|
|
curAnimState->x2 = curAnimState->x1;
|
|
|
|
curAnimState->y2 = curAnimState->y1;
|
|
|
|
curAnimState->active = 1;
|
|
|
|
curAnimState->refreshFlag = 1;
|
|
|
|
curAnimState->bkgdChangeFlag = 1;
|
|
|
|
|
|
|
|
if (ch->facing >= 1 && ch->facing <= 3) {
|
|
|
|
curAnimState->flags |= 1;
|
|
|
|
} else if (ch->facing >= 5 && ch->facing <= 7) {
|
|
|
|
curAnimState->flags &= 0xFFFFFFFE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_objectQueue = objectQueue(_objectQueue, curAnimState);
|
|
|
|
|
|
|
|
++addedObjects;
|
|
|
|
++listAdded;
|
|
|
|
if (listAdded < 2)
|
|
|
|
i = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
2005-11-10 14:08:50 +00:00
|
|
|
curAnimState = &_sprites->_animObjects[i];
|
|
|
|
|
|
|
|
if (_sprites->_anims[i].play) {
|
|
|
|
curAnimState->active = 1;
|
|
|
|
curAnimState->refreshFlag = 1;
|
|
|
|
curAnimState->bkgdChangeFlag = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
curAnimState->active = 0;
|
|
|
|
curAnimState->refreshFlag = 0;
|
|
|
|
curAnimState->bkgdChangeFlag = 0;
|
|
|
|
}
|
|
|
|
curAnimState->height = _sprites->_anims[i].height;
|
|
|
|
curAnimState->height2 = _sprites->_anims[i].height2;
|
|
|
|
curAnimState->width = _sprites->_anims[i].width + 1;
|
|
|
|
curAnimState->width2 = _sprites->_anims[i].width2;
|
|
|
|
curAnimState->drawY = _sprites->_anims[i].drawY;
|
|
|
|
curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
|
|
|
|
curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
|
|
|
|
curAnimState->background = _sprites->_anims[i].background;
|
|
|
|
curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
|
|
|
|
|
|
|
|
if(_sprites->_anims[i].unk2)
|
|
|
|
curAnimState->flags = 0x800;
|
|
|
|
else
|
|
|
|
curAnimState->flags = 0;
|
|
|
|
|
|
|
|
if (_sprites->_anims[i].flipX)
|
|
|
|
curAnimState->flags |= 0x1;
|
|
|
|
|
|
|
|
_objectQueue = objectQueue(_objectQueue, curAnimState);
|
|
|
|
|
2005-10-30 19:58:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 12; ++i) {
|
|
|
|
curAnimState = &_animItems[i];
|
|
|
|
Room *curRoom = &_roomTable[_currentCharacter->sceneId];
|
|
|
|
byte curItem = curRoom->itemsTable[i];
|
|
|
|
if (curItem != 0xFF) {
|
|
|
|
curAnimState->drawY = curRoom->itemsYPos[i];
|
2005-12-09 23:02:16 +00:00
|
|
|
curAnimState->sceneAnimPtr = _shapes[220+curItem];
|
2005-10-30 19:58:51 +00:00
|
|
|
curAnimState->animFrameNumber = 0xFFFF;
|
|
|
|
curAnimState->y1 = curRoom->itemsYPos[i];
|
|
|
|
curAnimState->x1 = curRoom->itemsXPos[i];
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
curAnimState->x1 -= (fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
|
|
|
|
curAnimState->y1 -= fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
|
2005-10-30 19:58:51 +00:00
|
|
|
|
|
|
|
curAnimState->x2 = curAnimState->x1;
|
|
|
|
curAnimState->y2 = curAnimState->y1;
|
|
|
|
|
|
|
|
curAnimState->active = 1;
|
|
|
|
curAnimState->refreshFlag = 1;
|
|
|
|
curAnimState->bkgdChangeFlag = 1;
|
|
|
|
|
|
|
|
_objectQueue = objectQueue(_objectQueue, curAnimState);
|
|
|
|
} else {
|
|
|
|
curAnimState->active = 0;
|
|
|
|
curAnimState->refreshFlag = 0;
|
|
|
|
curAnimState->bkgdChangeFlag = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
curAnimState = _charactersAnimState;
|
|
|
|
curAnimState->bkgdChangeFlag = 1;
|
|
|
|
curAnimState->refreshFlag = 1;
|
2005-12-20 10:58:07 +00:00
|
|
|
for (int i = 1; i < 28; ++i) {
|
|
|
|
curAnimState = &_animStates[i];
|
2005-10-30 19:58:51 +00:00
|
|
|
if (curAnimState->active) {
|
|
|
|
curAnimState->bkgdChangeFlag = 1;
|
|
|
|
curAnimState->refreshFlag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
prepDrawAllObjects();
|
2005-11-10 14:08:50 +00:00
|
|
|
initSceneScreen(brandonAlive);
|
2005-10-30 19:58:51 +00:00
|
|
|
copyChangedObjectsForward(0);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
void KyraEngine::initSceneScreen(int brandonAlive) {
|
|
|
|
// XXX (Pointless?) Palette stuff
|
2005-12-13 16:56:33 +00:00
|
|
|
if (_unkScreenVar2 == 1) {
|
|
|
|
_screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
|
|
|
|
} else {
|
|
|
|
_screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
2005-11-10 14:08:50 +00:00
|
|
|
// XXX More (pointless?) palette stuff
|
|
|
|
|
|
|
|
if (!_scriptInterpreter->startScript(_scriptClick, 2))
|
|
|
|
error("Could not start script function 2 of scene script");
|
|
|
|
|
|
|
|
_scriptClick->variables[7] = brandonAlive;
|
|
|
|
|
|
|
|
while (_scriptInterpreter->validScript(_scriptClick))
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
setTextFadeTimerCountdown(-1);
|
2005-12-23 17:49:14 +00:00
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
if (_itemInHand != -1)
|
|
|
|
magicOutMouseItem(2, -1);
|
|
|
|
|
|
|
|
_screen->hideMouse();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
if (_currentCharacter->inventoryItems[i] != 0xFF)
|
|
|
|
magicOutMouseItem(2, i);
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
2005-11-10 14:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
#pragma mark -
|
2005-11-10 21:42:42 +00:00
|
|
|
#pragma mark - Text handling
|
2005-10-29 18:37:40 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
void KyraEngine::setTalkCoords(uint16 y) {
|
|
|
|
debug(9, "KyraEngine::setTalkCoords(%d)", y);
|
|
|
|
_talkCoords.y = y;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
int KyraEngine::getCenterStringX(const char *str, int x1, int x2) {
|
|
|
|
debug(9, "KyraEngine::getCenterStringX('%s', %d, %d)", str, x1, x2);
|
|
|
|
_screen->_charWidth = -2;
|
|
|
|
Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
|
|
|
|
int strWidth = _screen->getTextWidth(str);
|
|
|
|
_screen->setFont(curFont);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
int w = x2 - x1 + 1;
|
|
|
|
return x1 + (w - strWidth) / 2;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
int KyraEngine::getCharLength(const char *str, int len) {
|
|
|
|
debug(9, "KyraEngine::getCharLength('%s', %d)", str, len);
|
|
|
|
int charsCount = 0;
|
|
|
|
if (*str) {
|
|
|
|
_screen->_charWidth = -2;
|
|
|
|
Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
|
|
|
|
int i = 0;
|
|
|
|
while (i <= len && *str) {
|
|
|
|
i += _screen->getCharWidth(*str++);
|
|
|
|
++charsCount;
|
|
|
|
}
|
|
|
|
_screen->setFont(curFont);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
}
|
|
|
|
return charsCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::dropCRIntoString(char *str, int offs) {
|
|
|
|
debug(9, "KyraEngine::dropCRIntoString('%s', %d)", str, offs);
|
|
|
|
int pos = 0;
|
|
|
|
str += offs;
|
|
|
|
while (*str) {
|
|
|
|
if (*str == ' ') {
|
|
|
|
*str = '\r';
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
++str;
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *KyraEngine::preprocessString(const char *str) {
|
|
|
|
debug(9, "KyraEngine::preprocessString('%s')", str);
|
|
|
|
assert(strlen(str) < sizeof(_talkBuffer) - 1);
|
|
|
|
strcpy(_talkBuffer, str);
|
|
|
|
char *p = _talkBuffer;
|
|
|
|
while (*p) {
|
|
|
|
if (*p == '\r') {
|
|
|
|
return _talkBuffer;
|
|
|
|
}
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
p = _talkBuffer;
|
|
|
|
Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
|
|
|
|
_screen->_charWidth = -2;
|
|
|
|
int textWidth = _screen->getTextWidth(p);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
if (textWidth > 176) {
|
|
|
|
if (textWidth > 352) {
|
|
|
|
int count = getCharLength(p, textWidth / 3);
|
|
|
|
int offs = dropCRIntoString(p, count);
|
|
|
|
p += count + offs;
|
|
|
|
_screen->_charWidth = -2;
|
|
|
|
textWidth = _screen->getTextWidth(p);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
count = getCharLength(p, textWidth / 2);
|
|
|
|
dropCRIntoString(p, count);
|
|
|
|
} else {
|
|
|
|
int count = getCharLength(p, textWidth / 2);
|
|
|
|
dropCRIntoString(p, count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->setFont(curFont);
|
|
|
|
return _talkBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::buildMessageSubstrings(const char *str) {
|
|
|
|
debug(9, "KyraEngine::buildMessageSubstrings('%s')", str);
|
|
|
|
int currentLine = 0;
|
|
|
|
int pos = 0;
|
|
|
|
while (*str) {
|
|
|
|
if (*str == '\r') {
|
|
|
|
assert(currentLine < TALK_SUBSTRING_NUM);
|
|
|
|
_talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = '\0';
|
|
|
|
++currentLine;
|
|
|
|
pos = 0;
|
|
|
|
} else {
|
|
|
|
_talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = *str;
|
|
|
|
++pos;
|
|
|
|
if (pos > TALK_SUBSTRING_LEN - 2) {
|
|
|
|
pos = TALK_SUBSTRING_LEN - 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++str;
|
|
|
|
}
|
|
|
|
_talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = '\0';
|
|
|
|
return currentLine + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::getWidestLineWidth(int linesCount) {
|
|
|
|
debug(9, "KyraEngine::getWidestLineWidth(%d)", linesCount);
|
|
|
|
int maxWidth = 0;
|
|
|
|
Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
|
|
|
|
_screen->_charWidth = -2;
|
|
|
|
for (int l = 0; l < linesCount; ++l) {
|
|
|
|
int w = _screen->getTextWidth(&_talkSubstrings[l * TALK_SUBSTRING_LEN]);
|
|
|
|
if (maxWidth < w) {
|
|
|
|
maxWidth = w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->setFont(curFont);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
return maxWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::calcWidestLineBounds(int &x1, int &x2, int w, int cx) {
|
|
|
|
debug(9, "KyraEngine::calcWidestLineBounds(%d, %d)", w, cx);
|
|
|
|
x1 = cx - w / 2;
|
|
|
|
if (x1 + w >= Screen::SCREEN_W - 12) {
|
|
|
|
x1 = Screen::SCREEN_W - 12 - w - 1;
|
|
|
|
} else if (x1 < 12) {
|
|
|
|
x1 = 12;
|
|
|
|
}
|
|
|
|
x2 = x1 + w + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::restoreTalkTextMessageBkgd(int srcPage, int dstPage) {
|
|
|
|
debug(9, "KyraEngine::restoreTalkTextMessageBkgd(%d, %d)", srcPage, dstPage);
|
|
|
|
if (_talkMessagePrinted) {
|
|
|
|
_talkMessagePrinted = false;
|
|
|
|
_screen->copyRegion(_talkCoords.x, _talkCoords.y, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage) {
|
|
|
|
debug(9, "KyraEngine::printTalkTextMessage('%s', %d, %d, %d, %d, %d)", text, x, y, color, srcPage, dstPage);
|
|
|
|
char *str = preprocessString(text);
|
|
|
|
int lineCount = buildMessageSubstrings(str);
|
|
|
|
int top = y - lineCount * 10;
|
|
|
|
if (top < 0) {
|
|
|
|
top = 0;
|
|
|
|
}
|
|
|
|
_talkMessageY = top;
|
|
|
|
_talkMessageH = lineCount * 10;
|
|
|
|
int w = getWidestLineWidth(lineCount);
|
|
|
|
int x1, x2;
|
|
|
|
calcWidestLineBounds(x1, x2, w, x);
|
|
|
|
_talkCoords.x = x1;
|
|
|
|
_talkCoords.w = w + 2;
|
|
|
|
_screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage);
|
|
|
|
int curPage = _screen->_curPage;
|
|
|
|
_screen->_curPage = srcPage;
|
|
|
|
for (int i = 0; i < lineCount; ++i) {
|
|
|
|
top = i * 10 + _talkMessageY;
|
|
|
|
char *msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN];
|
|
|
|
int left = getCenterStringX(msg, x1, x2);
|
|
|
|
printText(msg, left, top, color, 0xC, 0);
|
|
|
|
}
|
|
|
|
_screen->_curPage = curPage;
|
|
|
|
_talkMessagePrinted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2) {
|
|
|
|
uint8 colorMap[] = { 0, 15, 12, 12 };
|
|
|
|
colorMap[3] = c1;
|
|
|
|
_screen->setTextColor(colorMap, 0, 3);
|
|
|
|
Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
|
|
|
|
_screen->_charWidth = -2;
|
|
|
|
_screen->printText(str, x, y, c0, c2);
|
|
|
|
_screen->_charWidth = 0;
|
|
|
|
_screen->setFont(curFont);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 charNum) {
|
|
|
|
debug(9, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum);
|
|
|
|
bool hasUpdatedNPCs = false;
|
|
|
|
bool runLoop = true;
|
|
|
|
uint8 currPage;
|
|
|
|
OSystem::Event event;
|
2005-11-11 22:17:06 +00:00
|
|
|
int16 delayTime;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
//while( towns_isEscKeyPressed() )
|
|
|
|
//towns_getKey();
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
if (chatDuration != -1 ) {
|
2005-11-11 22:17:06 +00:00
|
|
|
switch (_configTalkspeed) {
|
2005-11-10 14:08:50 +00:00
|
|
|
case 0: chatDuration *= 2;
|
|
|
|
break;
|
|
|
|
case 2: chatDuration /= 4;
|
|
|
|
break;
|
|
|
|
case 3: chatDuration = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chatDuration != -1)
|
2005-11-11 22:17:06 +00:00
|
|
|
chatDuration *= _tickLength;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
disableTimer(14);
|
|
|
|
disableTimer(18);
|
|
|
|
disableTimer(19);
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
uint32 timeAtStart = _system->getMillis();
|
|
|
|
uint32 loopStart;
|
|
|
|
while (runLoop) {
|
|
|
|
loopStart = _system->getMillis();
|
|
|
|
/*
|
|
|
|
if (_currentCharacter.sceneId == 0xD2)
|
|
|
|
if (seq_playEnd())
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) {
|
2005-11-10 14:08:50 +00:00
|
|
|
hasUpdatedNPCs = true;
|
2005-11-11 22:17:06 +00:00
|
|
|
disableTimer(15);
|
2005-12-09 14:52:31 +00:00
|
|
|
_currHeadShape = 4;
|
2005-11-10 14:08:50 +00:00
|
|
|
animRefreshNPC(0);
|
2005-12-09 14:52:31 +00:00
|
|
|
animRefreshNPC(_talkingCharNum);
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
if (_charSayUnk2 != -1) {
|
|
|
|
_sprites->_animObjects[_charSayUnk2].active = 0;
|
|
|
|
_sprites->_anims[_charSayUnk2].play = false;
|
|
|
|
_charSayUnk2 = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
updateGameTimers();
|
2005-11-10 14:08:50 +00:00
|
|
|
_sprites->updateSceneAnims();
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
prepDrawAllObjects();
|
|
|
|
|
|
|
|
currPage = _screen->_curPage;
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
printCharacterText(chatStr, charNum);
|
|
|
|
_screen->_curPage = currPage;
|
|
|
|
|
|
|
|
copyChangedObjectsForward(0);
|
2005-12-09 14:52:31 +00:00
|
|
|
updateTextFade();
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
while (_system->pollEvent(event)) {
|
|
|
|
switch (event.type) {
|
|
|
|
case OSystem::EVENT_KEYDOWN:
|
2005-12-10 17:51:40 +00:00
|
|
|
if (event.kbd.keycode == '.')
|
2005-11-10 14:08:50 +00:00
|
|
|
runLoop = false;
|
|
|
|
break;
|
|
|
|
case OSystem::EVENT_QUIT:
|
|
|
|
quitGame();
|
|
|
|
case OSystem::EVENT_LBUTTONDOWN:
|
|
|
|
runLoop = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-12-10 17:51:40 +00:00
|
|
|
|
|
|
|
if (_fastMode)
|
|
|
|
runLoop = false;
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
delayTime = (loopStart + _gameSpeed) - _system->getMillis();
|
|
|
|
if (delayTime > 0)
|
|
|
|
_system->delayMillis(delayTime);
|
2005-11-10 14:08:50 +00:00
|
|
|
}
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
enableTimer(14);
|
|
|
|
enableTimer(15);
|
|
|
|
enableTimer(18);
|
|
|
|
enableTimer(19);
|
|
|
|
//clearKyrandiaButtonIO();
|
2005-11-10 14:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::endCharacterChat(int8 charNum, int16 convoInitialized) {
|
|
|
|
_charSayUnk3 = -1;
|
|
|
|
|
|
|
|
if (charNum > 4 && charNum < 11) {
|
|
|
|
//TODO: weird _game_inventory stuff here
|
2005-12-10 17:51:40 +00:00
|
|
|
warning("STUB: endCharacterChat() for high charnums");
|
2005-11-10 14:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (convoInitialized != 0) {
|
2005-12-09 14:52:31 +00:00
|
|
|
_talkingCharNum = -1;
|
2005-11-10 14:08:50 +00:00
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::restoreChatPartnerAnimFrame(int8 charNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
_talkingCharNum = -1;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
if (charNum > 0 && charNum < 5) {
|
|
|
|
_characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame;
|
|
|
|
animRefreshNPC(charNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
_talkingCharNum = 0;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
if (charNum < 5 && charNum > 0)
|
|
|
|
_currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame;
|
|
|
|
|
|
|
|
if (_scaleMode != 0)
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
else
|
|
|
|
_currentCharacter->currentAnimFrame = _currentCharAnimFrame;
|
|
|
|
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
}
|
|
|
|
|
|
|
|
int8 KyraEngine::getChatPartnerNum() {
|
|
|
|
uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A};
|
|
|
|
int pos = 0;
|
|
|
|
int partner = -1;
|
|
|
|
|
|
|
|
for (int i = 1; i < 6; i++) {
|
|
|
|
if (_currentCharacter->sceneId == sceneTable[pos]) {
|
|
|
|
partner = sceneTable[pos+1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pos += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < 5; i++) {
|
|
|
|
if (_characterList[i].sceneId == _currentCharacter->sceneId) {
|
|
|
|
partner = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return partner;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::initCharacterChat(int8 charNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
if (_talkingCharNum == -1) {
|
|
|
|
_talkingCharNum = 0;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
if (_scaleMode != 0)
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
else
|
|
|
|
_currentCharacter->currentAnimFrame = 16;
|
|
|
|
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
}
|
|
|
|
|
|
|
|
_charSayUnk2 = -1;
|
|
|
|
flagAllObjectsForBkgdChange();
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
if (charNum > 4 && charNum < 11) {
|
2005-11-10 14:08:50 +00:00
|
|
|
// TODO: Fill in weird _game_inventory stuff here
|
2005-12-10 17:51:40 +00:00
|
|
|
warning("STUB: initCharacterChat() for high charnums");
|
2005-11-10 14:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
flagAllObjectsForRefresh();
|
|
|
|
flagAllObjectsForBkgdChange();
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
_charSayUnk3 = charNum;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::printCharacterText(char *text, int8 charNum) {
|
|
|
|
uint8 colorTable[] = {0x0F, 0x9, 0x0C9, 0x80, 0x5, 0x81, 0x0E, 0xD8, 0x55, 0x3A, 0x3a};
|
|
|
|
int top, left, x1, x2, w, x;
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
uint8 color = colorTable[charNum];
|
|
|
|
text = preprocessString(text);
|
|
|
|
int lineCount = buildMessageSubstrings(text);
|
|
|
|
w = getWidestLineWidth(lineCount);
|
|
|
|
x = _characterList[charNum].x1;
|
|
|
|
calcWidestLineBounds(x1, x2, w, x);
|
|
|
|
|
|
|
|
for (int i = 0; i < lineCount; ++i) {
|
|
|
|
top = i * 10 + _talkMessageY;
|
|
|
|
msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN];
|
|
|
|
left = getCenterStringX(msg, x1, x2);
|
|
|
|
printText(msg, left, top, color, 0xC, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) {
|
2005-12-26 14:53:51 +00:00
|
|
|
debug(9, "KyraEngine::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration);
|
2005-11-10 14:08:50 +00:00
|
|
|
uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 };
|
|
|
|
|
|
|
|
uint16 chatTicks;
|
|
|
|
int16 convoInitialized;
|
|
|
|
int8 chatPartnerNum;
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
if (_currentCharacter->sceneId == 210)
|
2005-11-10 14:08:50 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
convoInitialized = initCharacterChat(charNum);
|
|
|
|
chatPartnerNum = getChatPartnerNum();
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
if (chatPartnerNum != -1 && chatPartnerNum < 5)
|
2005-11-10 14:08:50 +00:00
|
|
|
backupChatPartnerAnimFrame(chatPartnerNum);
|
|
|
|
|
|
|
|
if (charNum < 5) {
|
|
|
|
_characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
|
|
|
|
_charSayUnk3 = charNum;
|
2005-12-09 14:52:31 +00:00
|
|
|
_talkingCharNum = charNum;
|
2005-11-10 14:08:50 +00:00
|
|
|
animRefreshNPC(charNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *processedString = preprocessString(chatStr);
|
|
|
|
int lineNum = buildMessageSubstrings(processedString);
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
int16 yPos = _characterList[charNum].y1;
|
|
|
|
yPos -= _scaleTable[charNum] * _characterList[charNum].height;
|
|
|
|
yPos -= 8;
|
|
|
|
yPos -= lineNum * 10;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
if (yPos < 11)
|
|
|
|
yPos = 11;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
if (yPos > 100)
|
2005-11-11 22:17:06 +00:00
|
|
|
yPos = 100;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
_talkMessageY = yPos;
|
2005-11-10 14:08:50 +00:00
|
|
|
_talkMessageH = lineNum * 10;
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
|
|
|
|
_screen->copyRegion(1, _talkMessageY, 1, 136, 319, _talkMessageH, 2, 2);
|
|
|
|
_screen->hideMouse();
|
|
|
|
|
|
|
|
printCharacterText(processedString, charNum);
|
|
|
|
_screen->showMouse();
|
|
|
|
|
|
|
|
if (chatDuration == -2)
|
|
|
|
chatTicks = strlen(processedString) * 9;
|
|
|
|
else
|
|
|
|
chatTicks = chatDuration;
|
|
|
|
|
|
|
|
waitForChatToFinish(chatTicks, chatStr, charNum);
|
|
|
|
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
|
|
|
|
_screen->copyRegion(1, 136, 1, _talkMessageY, 319, _talkMessageH, 2, 2);
|
|
|
|
preserveAllBackgrounds();
|
|
|
|
prepDrawAllObjects();
|
|
|
|
_screen->hideMouse();
|
|
|
|
|
|
|
|
_screen->copyRegion(1, _talkMessageY, 1, _talkMessageY, 319, _talkMessageH, 2, 0);
|
|
|
|
_screen->showMouse();
|
|
|
|
flagAllObjectsForRefresh();
|
|
|
|
copyChangedObjectsForward(0);
|
|
|
|
|
|
|
|
if (chatPartnerNum != -1 && chatPartnerNum < 5)
|
|
|
|
restoreChatPartnerAnimFrame(chatPartnerNum);
|
|
|
|
|
|
|
|
endCharacterChat(charNum, convoInitialized);
|
|
|
|
}
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
void KyraEngine::drawSentenceCommand(char *sentence, int color) {
|
|
|
|
debug(9, "drawSentenceCommand('%s', %i)", sentence, color);
|
2005-11-10 14:08:50 +00:00
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->fillRect(8, 143, 311, 152, 12);
|
2005-12-09 14:52:31 +00:00
|
|
|
|
|
|
|
if (_startSentencePalIndex != color || _fadeText != false) {
|
|
|
|
_currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3];
|
|
|
|
_currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1];
|
|
|
|
_currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2];
|
|
|
|
|
|
|
|
_screen->setScreenPalette(_screen->_currentPalette);
|
|
|
|
_startSentencePalIndex = 0;
|
|
|
|
}
|
2005-11-10 14:08:50 +00:00
|
|
|
|
|
|
|
printText(sentence, 8, 143, 0xFF, 12, 0);
|
|
|
|
_screen->showMouse();
|
2005-12-09 14:52:31 +00:00
|
|
|
setTextFadeTimerCountdown(15);
|
|
|
|
_fadeText = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::updateSentenceCommand(char *str1, char *str2, int color) {
|
|
|
|
debug(9, "updateSentenceCommand('%s', '%s', %i)", str1, str2, color);
|
|
|
|
char sentenceCommand[500];
|
|
|
|
strncpy(sentenceCommand, str1, 500);
|
|
|
|
if (str2)
|
|
|
|
strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand));
|
|
|
|
|
|
|
|
drawSentenceCommand(sentenceCommand, color);
|
2005-12-18 18:50:15 +00:00
|
|
|
_screen->updateScreen();
|
2005-12-09 14:52:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::updateTextFade() {
|
|
|
|
debug(9, "updateTextFade()");
|
|
|
|
if (!_fadeText)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool finished = false;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
if (_currSentenceColor[i] > 4)
|
|
|
|
_currSentenceColor[i] -= 4;
|
|
|
|
else
|
|
|
|
if (_currSentenceColor[i]) {
|
|
|
|
_currSentenceColor[i] = 0;
|
|
|
|
finished = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
_screen->_currentPalette[765] = _currSentenceColor[0];
|
|
|
|
_screen->_currentPalette[766] = _currSentenceColor[1];
|
|
|
|
_screen->_currentPalette[767] = _currSentenceColor[2];
|
|
|
|
_screen->setScreenPalette(_screen->_currentPalette);
|
|
|
|
|
|
|
|
if (finished) {
|
|
|
|
_fadeText = false;
|
|
|
|
_startSentencePalIndex = -1;
|
|
|
|
}
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
}
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Item handling
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
void KyraEngine::addToNoDropRects(int x, int y, int w, int h) {
|
|
|
|
debug(9, "addToNoDropRects(%d, %d, %d, %d)", x, y, w, h);
|
|
|
|
for (int rect = 0; rect < 11; ++rect) {
|
|
|
|
if (_noDropRects[rect].x == -1) {
|
|
|
|
_noDropRects[rect].x = x;
|
|
|
|
_noDropRects[rect].y = y;
|
|
|
|
_noDropRects[rect].x2 = x + w - 1;
|
|
|
|
_noDropRects[rect].y2 = y + h - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::clearNoDropRects() {
|
|
|
|
debug(9, "clearNoDropRects()");
|
|
|
|
memset(_noDropRects, -1, sizeof(_noDropRects));
|
|
|
|
}
|
|
|
|
|
|
|
|
byte KyraEngine::findFreeItemInScene(int scene) {
|
|
|
|
debug(9, "findFreeItemInScene(%d)", scene);
|
|
|
|
assert(scene < _roomTableSize);
|
|
|
|
Room *room = &_roomTable[scene];
|
2005-10-29 18:37:40 +00:00
|
|
|
for (int i = 0; i < 12; ++i) {
|
2005-12-08 17:19:18 +00:00
|
|
|
if (room->itemsTable[i] == 0xFF)
|
2005-10-29 18:37:40 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
byte KyraEngine::findItemAtPos(int x, int y) {
|
2005-11-09 22:26:12 +00:00
|
|
|
debug(9, "findItemAtPos(%d, %d)", x, y);
|
2005-10-29 18:37:40 +00:00
|
|
|
assert(_currentCharacter->sceneId < _roomTableSize);
|
2005-12-09 17:36:57 +00:00
|
|
|
const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable;
|
|
|
|
const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos;
|
|
|
|
const uint8 *yposOffset = _roomTable[_currentCharacter->sceneId].itemsYPos;
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
int highestYPos = -1;
|
|
|
|
byte returnValue = 0xFF;
|
|
|
|
|
|
|
|
for (int i = 0; i < 12; ++i) {
|
|
|
|
if (*itemsTable != 0xFF) {
|
2005-12-09 17:36:57 +00:00
|
|
|
int xpos = *xposOffset - 11;
|
2005-10-29 18:37:40 +00:00
|
|
|
int xpos2 = *xposOffset + 10;
|
|
|
|
if (x > xpos && x < xpos2) {
|
|
|
|
assert(*itemsTable < ARRAYSIZE(_itemTable));
|
|
|
|
int itemHeight = _itemTable[*itemsTable].height;
|
2005-12-09 17:36:57 +00:00
|
|
|
int ypos = *yposOffset + 3;
|
2005-10-29 18:37:40 +00:00
|
|
|
int ypos2 = ypos - itemHeight - 3;
|
|
|
|
|
2005-12-09 17:36:57 +00:00
|
|
|
if (y > ypos2 && ypos > y) {
|
2005-10-29 18:37:40 +00:00
|
|
|
if (highestYPos <= ypos) {
|
|
|
|
returnValue = i;
|
|
|
|
highestYPos = ypos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-12-09 17:36:57 +00:00
|
|
|
++xposOffset;
|
|
|
|
++yposOffset;
|
|
|
|
++itemsTable;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::placeItemInGenericMapScene(int item, int index) {
|
|
|
|
debug(9, "placeItemInGenericMapScene(%d, %d)", item, index);
|
|
|
|
static const uint16 itemMapSceneMinTable[] = {
|
|
|
|
0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000
|
|
|
|
};
|
|
|
|
static const uint16 itemMapSceneMaxTable[] = {
|
|
|
|
0x0010, 0x0024, 0x00C6, 0x006C, 0x00F5, 0x0000
|
|
|
|
};
|
|
|
|
|
|
|
|
int minValue = itemMapSceneMinTable[index];
|
|
|
|
int maxValue = itemMapSceneMaxTable[index];
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
int room = _rnd.getRandomNumberRng(minValue, maxValue);
|
|
|
|
assert(room < _roomTableSize);
|
|
|
|
int nameIndex = _roomTable[room].nameIndex;
|
|
|
|
bool placeItem = false;
|
|
|
|
|
|
|
|
switch (nameIndex) {
|
|
|
|
case 0: case 1: case 2: case 3:
|
|
|
|
case 4: case 5: case 6: case 11:
|
|
|
|
case 12: case 16: case 17: case 20:
|
|
|
|
case 22: case 23: case 25: case 26:
|
|
|
|
case 27: case 31: case 33: case 34:
|
|
|
|
case 36: case 37: case 58: case 59:
|
|
|
|
case 60: case 61: case 83: case 84:
|
|
|
|
case 85: case 104: case 105: case 106:
|
|
|
|
placeItem = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 51:
|
|
|
|
if (room != 46) {
|
|
|
|
placeItem = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
placeItem = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (placeItem) {
|
|
|
|
Room *roomPtr = &_roomTable[room];
|
|
|
|
if (roomPtr->northExit == 0xFFFF && roomPtr->eastExit == 0xFFFF && roomPtr->southExit == 0xFFFF && roomPtr->westExit == 0xFFFF) {
|
|
|
|
placeItem = false;
|
|
|
|
} else if (_currentCharacter->sceneId == room) {
|
|
|
|
placeItem = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (placeItem) {
|
2005-12-09 19:49:47 +00:00
|
|
|
if (!processItemDrop(room, item, -1, -1, 2, 0))
|
2005-12-08 17:19:18 +00:00
|
|
|
continue;
|
2005-10-29 18:37:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
void KyraEngine::createMouseItem(int item) {
|
|
|
|
debug(9, "createMouseItem(%d)", item);
|
|
|
|
_screen->hideMouse();
|
|
|
|
setMouseItem(item);
|
|
|
|
_itemInHand = item;
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::destroyMouseItem() {
|
|
|
|
debug(9, "destroyMouseItem()");
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->setMouseCursor(1, 1, _shapes[4]);
|
|
|
|
_itemInHand = -1;
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setMouseItem(int item) {
|
|
|
|
debug(9, "setMouseItem(%d)", item);
|
|
|
|
if (item == -1) {
|
|
|
|
_screen->setMouseCursor(1, 1, _shapes[10]);
|
|
|
|
} else {
|
|
|
|
_screen->setMouseCursor(8, 15, _shapes[220+item]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::wipeDownMouseItem(int xpos, int ypos) {
|
|
|
|
debug(9, "wipeDownMouseItem(%d, %d)", xpos, ypos);
|
|
|
|
if (_itemInHand == -1)
|
|
|
|
return;
|
|
|
|
xpos -= 8;
|
|
|
|
ypos -= 15;
|
|
|
|
_screen->hideMouse();
|
|
|
|
backUpRect1(xpos, ypos);
|
|
|
|
int y = ypos;
|
|
|
|
int height = 16;
|
|
|
|
|
|
|
|
while (height >= 0) {
|
|
|
|
restoreRect1(xpos, ypos);
|
|
|
|
_screen->setNewShapeHeight(_shapes[220+_itemInHand], height);
|
2005-12-24 18:00:35 +00:00
|
|
|
uint32 nextTime = _system->getMillis() + 1 * _tickLength;
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->drawShape(0, _shapes[220+_itemInHand], xpos, y, 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
y += 2;
|
|
|
|
height -= 2;
|
2005-12-24 18:00:35 +00:00
|
|
|
while (_system->getMillis() < nextTime) {}
|
2005-11-18 23:55:31 +00:00
|
|
|
}
|
|
|
|
restoreRect1(xpos, ypos);
|
|
|
|
_screen->resetShapeHeight(_shapes[220+_itemInHand]);
|
|
|
|
destroyMouseItem();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
void KyraEngine::setupSceneItems() {
|
|
|
|
debug(9, "setupSceneItems()");
|
|
|
|
uint16 sceneId = _currentCharacter->sceneId;
|
|
|
|
assert(sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
|
|
|
for (int i = 0; i < 12; ++i) {
|
|
|
|
uint8 item = currentRoom->itemsTable[i];
|
|
|
|
if (item == 0xFF || !currentRoom->unkField3[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int xpos = 0;
|
|
|
|
int ypos = 0;
|
|
|
|
|
|
|
|
if (currentRoom->itemsXPos[i] == 0xFFFF) {
|
|
|
|
xpos = currentRoom->itemsXPos[i] = _rnd.getRandomNumberRng(24, 296);
|
|
|
|
ypos = currentRoom->itemsYPos[i] = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 130);
|
|
|
|
} else {
|
|
|
|
xpos = currentRoom->itemsXPos[i];
|
|
|
|
ypos = currentRoom->itemsYPos[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
_lastProcessedItem = i;
|
|
|
|
|
|
|
|
int stop = 0;
|
|
|
|
while (!stop) {
|
2005-12-09 19:49:47 +00:00
|
|
|
stop = processItemDrop(sceneId, item, xpos, ypos, 3, 0);
|
2005-12-08 17:19:18 +00:00
|
|
|
if (!stop) {
|
|
|
|
xpos = currentRoom->itemsXPos[i] = _rnd.getRandomNumberRng(24, 296);
|
|
|
|
ypos = currentRoom->itemsYPos[i] = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 130);
|
|
|
|
if (countItemsInScene(sceneId) >= 12) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
currentRoom->unkField3[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::countItemsInScene(uint16 sceneId) {
|
|
|
|
debug(9, "countItemsInScene(%d)", sceneId);
|
|
|
|
assert(sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
|
|
|
|
|
|
|
int items = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < 12; ++i) {
|
|
|
|
if (currentRoom->itemsTable[i] != 0xFF) {
|
|
|
|
++items;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) {
|
|
|
|
debug(9, "processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2);
|
2005-12-08 17:19:18 +00:00
|
|
|
int freeItem = -1;
|
|
|
|
uint8 itemIndex = findItemAtPos(x, y);
|
|
|
|
if (unk1) {
|
|
|
|
itemIndex = 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (itemIndex != 0xFF) {
|
|
|
|
exchangeItemWithMouseItem(sceneId, itemIndex);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
|
|
|
|
|
|
|
if (unk1 != 3) {
|
|
|
|
for (int i = 0; i < 12; ++i) {
|
|
|
|
if (currentRoom->itemsTable[i] == 0xFF) {
|
|
|
|
freeItem = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
freeItem = _lastProcessedItem;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (freeItem == -1) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sceneId != _currentCharacter->sceneId) {
|
|
|
|
addItemToRoom(sceneId, item, freeItem, x, y);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int itemHeight = _itemTable[item].height;
|
|
|
|
_lastProcessedItemHeight = itemHeight;
|
|
|
|
|
|
|
|
if (x == -1 && x == -1) {
|
|
|
|
x = _rnd.getRandomNumberRng(16, 304);
|
|
|
|
y = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 135);
|
|
|
|
}
|
|
|
|
|
|
|
|
int xpos = x;
|
|
|
|
int ypos = y;
|
|
|
|
int destY = -1;
|
|
|
|
int destX = -1;
|
|
|
|
int running = 1;
|
2005-12-09 19:49:47 +00:00
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
while (running) {
|
|
|
|
if ((_northExitHeight & 0xFF) <= ypos) {
|
|
|
|
bool running2 = true;
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
if (getDrawLayer(xpos, ypos) > 1) {
|
2005-12-08 17:19:18 +00:00
|
|
|
if (((_northExitHeight >> 8) & 0xFF) != ypos) {
|
|
|
|
running2 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
if (getDrawLayer2(xpos, ypos, itemHeight) > 1) {
|
2005-12-08 17:19:18 +00:00
|
|
|
if (((_northExitHeight >> 8) & 0xFF) != ypos) {
|
|
|
|
running2 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isDropable(xpos, ypos)) {
|
|
|
|
if (((_northExitHeight >> 8) & 0xFF) != ypos) {
|
|
|
|
running2 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int xpos2 = xpos;
|
|
|
|
int xpos3 = xpos;
|
|
|
|
|
|
|
|
while (running2) {
|
|
|
|
if (isDropable(xpos2, ypos)) {
|
|
|
|
if (getDrawLayer2(xpos2, ypos, itemHeight) < 7) {
|
|
|
|
if (findItemAtPos(xpos2, ypos) == 0xFF) {
|
|
|
|
destX = xpos2;
|
|
|
|
destY = ypos;
|
|
|
|
running = 0;
|
|
|
|
running2 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isDropable(xpos3, ypos)) {
|
|
|
|
if (getDrawLayer2(xpos3, ypos, itemHeight) < 7) {
|
|
|
|
if (findItemAtPos(xpos3, ypos) == 0xFF) {
|
|
|
|
destX = xpos3;
|
|
|
|
destY = ypos;
|
|
|
|
running = 0;
|
|
|
|
running2 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!running2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
xpos2 -= 2;
|
|
|
|
if (xpos2 < 16) {
|
|
|
|
xpos2 = 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
xpos3 += 2;
|
|
|
|
if (xpos3 > 304) {
|
|
|
|
xpos3 = 304;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos2 > 16)
|
|
|
|
continue;
|
|
|
|
if (xpos3 < 304)
|
|
|
|
continue;
|
|
|
|
running2 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((_northExitHeight >> 8) & 0xFF) == ypos) {
|
|
|
|
running = 0;
|
|
|
|
destY -= _rnd.getRandomNumberRng(0, 3);
|
|
|
|
|
|
|
|
if ((_northExitHeight & 0xFF) < destY) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
destY = (_northExitHeight & 0xFF) + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ypos += 2;
|
|
|
|
if (((_northExitHeight >> 8) & 0xFF) >= ypos) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ypos = (_northExitHeight >> 8) & 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (destX == -1 || destY == -1) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unk1 == 3) {
|
|
|
|
currentRoom->itemsXPos[freeItem] = destX;
|
|
|
|
currentRoom->itemsYPos[freeItem] = destY;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unk1 == 2) {
|
2005-12-22 18:14:52 +00:00
|
|
|
itemSpecialFX(x, y, item);
|
2005-12-08 17:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (unk1 == 0) {
|
|
|
|
destroyMouseItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
itemDropDown(x, y, destX, destY, freeItem, item);
|
|
|
|
|
|
|
|
if (unk1 == 0 && unk2 != 0) {
|
2005-12-14 14:08:30 +00:00
|
|
|
assert(_itemList && _droppedList);
|
|
|
|
updateSentenceCommand(_itemList[item], _droppedList[0], 179);
|
2005-12-08 17:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) {
|
|
|
|
debug(9, "exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex);
|
|
|
|
_screen->hideMouse();
|
|
|
|
animRemoveGameItem(itemIndex);
|
|
|
|
assert(sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
|
|
|
|
2005-12-09 17:36:57 +00:00
|
|
|
int item = currentRoom->itemsTable[itemIndex];
|
2005-12-08 17:19:18 +00:00
|
|
|
currentRoom->itemsTable[itemIndex] = _itemInHand;
|
|
|
|
_itemInHand = item;
|
|
|
|
animAddGameItem(itemIndex, sceneId);
|
|
|
|
// XXX snd_kyraPlaySound 53
|
|
|
|
|
|
|
|
setMouseItem(_itemInHand);
|
2005-12-14 14:08:30 +00:00
|
|
|
assert(_itemList && _takenList);
|
|
|
|
updateSentenceCommand(_itemList[_itemInHand], _takenList[1], 179);
|
2005-12-08 17:19:18 +00:00
|
|
|
_screen->showMouse();
|
|
|
|
clickEventHandler2();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) {
|
|
|
|
debug(9, "addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y);
|
|
|
|
assert(sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
|
|
|
currentRoom->itemsTable[itemIndex] = item;
|
|
|
|
currentRoom->itemsXPos[itemIndex] = x;
|
|
|
|
currentRoom->itemsYPos[itemIndex] = y;
|
|
|
|
currentRoom->unkField3[itemIndex] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::checkNoDropRects(int x, int y) {
|
|
|
|
debug(9, "checkNoDropRects(%d, %d)", x, y);
|
|
|
|
if (_lastProcessedItemHeight < 1 || _lastProcessedItemHeight > 16) {
|
|
|
|
_lastProcessedItemHeight = 16;
|
|
|
|
}
|
|
|
|
if (_noDropRects[0].x == -1) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
if (_noDropRects[i].x == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int xpos = _noDropRects[i].x;
|
|
|
|
int ypos = _noDropRects[i].y;
|
|
|
|
int xpos2 = _noDropRects[i].x2;
|
|
|
|
int ypos2 = _noDropRects[i].y2;
|
|
|
|
|
|
|
|
if (xpos > x + 16)
|
|
|
|
continue;
|
|
|
|
if (xpos2 < x)
|
|
|
|
continue;
|
|
|
|
if (y < ypos)
|
|
|
|
continue;
|
|
|
|
if (ypos2 < y - _lastProcessedItemHeight)
|
|
|
|
continue;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::isDropable(int x, int y) {
|
|
|
|
debug(9, "isDropable(%d, %d)", x, y);
|
|
|
|
x -= 8;
|
|
|
|
y -= 1;
|
|
|
|
|
|
|
|
if (checkNoDropRects(x, y)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int xpos = x; xpos < x + 16; ++xpos) {
|
|
|
|
if (_screen->getShapeFlag1(xpos, y) == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) {
|
|
|
|
debug(9, "itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item);
|
|
|
|
assert(_currentCharacter->sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
|
|
|
|
if (x == destX && y == destY) {
|
|
|
|
currentRoom->itemsXPos[freeItem] = destX;
|
|
|
|
currentRoom->itemsYPos[freeItem] = destY;
|
|
|
|
currentRoom->itemsTable[freeItem] = item;
|
|
|
|
// call kyraPlaySound(0x32)
|
|
|
|
animAddGameItem(freeItem, _currentCharacter->sceneId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_screen->hideMouse();
|
|
|
|
if (y <= destY) {
|
|
|
|
int tempY = y;
|
|
|
|
int addY = 2;
|
|
|
|
int drawX = x - 8;
|
|
|
|
int drawY = 0;
|
|
|
|
|
|
|
|
backUpRect0(drawX, y - 16);
|
|
|
|
|
|
|
|
while (tempY < destY) {
|
|
|
|
restoreRect0(drawX, tempY - 16);
|
|
|
|
tempY += addY;
|
|
|
|
if (tempY > destY) {
|
|
|
|
tempY = destY;
|
|
|
|
}
|
|
|
|
++addY;
|
|
|
|
drawY = tempY - 16;
|
|
|
|
backUpRect0(drawX, drawY);
|
2005-12-22 18:14:52 +00:00
|
|
|
uint32 nextTime = _system->getMillis() + 1 * _tickLength;
|
2005-12-08 17:19:18 +00:00
|
|
|
_screen->drawShape(0, _shapes[220+item], drawX, drawY, 0, 0);
|
|
|
|
_screen->updateScreen();
|
2005-12-22 18:14:52 +00:00
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if ((nextTime - _system->getMillis()) >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
2005-12-08 17:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool skip = false;
|
|
|
|
if (x == destX) {
|
|
|
|
if (destY - y <= 16) {
|
|
|
|
skip = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!skip) {
|
|
|
|
// call kyraPlaySound(0x47)
|
|
|
|
if (addY < 6)
|
|
|
|
addY = 6;
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
int xDiff = (destX - x) << 4;
|
2005-12-08 17:19:18 +00:00
|
|
|
xDiff /= addY;
|
|
|
|
int startAddY = addY;
|
2005-12-09 19:49:47 +00:00
|
|
|
addY >>= 1;
|
2005-12-08 17:19:18 +00:00
|
|
|
if (destY - y <= 8) {
|
|
|
|
addY >>= 1;
|
|
|
|
}
|
|
|
|
addY = -addY;
|
|
|
|
int unkX = x << 4;
|
|
|
|
while (--startAddY) {
|
|
|
|
drawX = (unkX >> 4) - 8;
|
|
|
|
drawY = tempY - 16;
|
|
|
|
restoreRect0(drawX, drawY);
|
|
|
|
tempY += addY;
|
|
|
|
unkX += xDiff;
|
|
|
|
if (tempY > destY) {
|
|
|
|
tempY = destY;
|
|
|
|
}
|
|
|
|
++addY;
|
|
|
|
drawX = (unkX >> 4) - 8;
|
|
|
|
drawY = tempY - 16;
|
|
|
|
backUpRect0(drawX, drawY);
|
2005-12-22 18:14:52 +00:00
|
|
|
uint32 nextTime = _system->getMillis() + 1 * _tickLength;
|
2005-12-08 17:19:18 +00:00
|
|
|
_screen->drawShape(0, _shapes[220+item], drawX, drawY, 0, 0);
|
|
|
|
_screen->updateScreen();
|
2005-12-22 18:14:52 +00:00
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if ((nextTime - _system->getMillis()) >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
2005-12-08 17:19:18 +00:00
|
|
|
}
|
2005-12-09 19:49:47 +00:00
|
|
|
restoreRect0(drawX, drawY);
|
2005-12-08 17:19:18 +00:00
|
|
|
} else {
|
|
|
|
restoreRect0(drawX, tempY - 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
currentRoom->itemsXPos[freeItem] = destX;
|
|
|
|
currentRoom->itemsYPos[freeItem] = destY;
|
|
|
|
currentRoom->itemsTable[freeItem] = item;
|
|
|
|
// call kyraPlaySound(0x32)
|
|
|
|
animAddGameItem(freeItem, _currentCharacter->sceneId);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) {
|
|
|
|
debug(9, "dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2);
|
|
|
|
if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2))
|
|
|
|
return;
|
|
|
|
// call kyraPlaySound(54)
|
|
|
|
if (12 == countItemsInScene(_currentCharacter->sceneId)) {
|
2005-12-14 14:08:30 +00:00
|
|
|
assert(_noDropList);
|
|
|
|
drawSentenceCommand(_noDropList[0], 6);
|
2005-12-09 19:49:47 +00:00
|
|
|
} else {
|
2005-12-14 14:08:30 +00:00
|
|
|
assert(_noDropList);
|
|
|
|
drawSentenceCommand(_noDropList[1], 6);
|
2005-12-09 19:49:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-22 18:14:52 +00:00
|
|
|
void KyraEngine::itemSpecialFX(int x, int y, int item) {
|
|
|
|
debug(9, "itemSpecialFX(%d, %d, %d)", x, y, item);
|
|
|
|
if (item == 41) {
|
|
|
|
itemSpecialFX1(x, y, item);
|
|
|
|
} else {
|
|
|
|
itemSpecialFX2(x, y, item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::itemSpecialFX1(int x, int y, int item) {
|
|
|
|
debug(9, "itemSpecialFX1(%d, %d, %d)", x, y, item);
|
|
|
|
uint8 *shape = _shapes[220+item];
|
|
|
|
x -= 8;
|
|
|
|
int startY = y;
|
|
|
|
y -= 15;
|
|
|
|
_screen->hideMouse();
|
|
|
|
backUpRect0(x, y);
|
|
|
|
for (int i = 1; i <= 16; ++i) {
|
|
|
|
_screen->setNewShapeHeight(shape, i);
|
|
|
|
--startY;
|
|
|
|
restoreRect0(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 1 * _tickLength;
|
|
|
|
_screen->drawShape(0, shape, x, startY, 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if ((nextTime - _system->getMillis()) >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
restoreRect0(x, y);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::itemSpecialFX2(int x, int y, int item) {
|
|
|
|
debug(9, "itemSpecialFX2(%d, %d, %d)", x, y, item);
|
|
|
|
x -= 8;
|
|
|
|
y -= 15;
|
|
|
|
int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF);
|
|
|
|
backUpRect0(x, y);
|
|
|
|
if (item >= 80 && item <= 89) {
|
|
|
|
// snd_kyraPlaySound(55);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 201; i <= 205; ++i) {
|
|
|
|
restoreRect0(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 3 * _tickLength;
|
|
|
|
_screen->drawShape(0, _shapes[4+i], x, y + yAdd, 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if ((nextTime - _system->getMillis()) >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 204; i >= 201; --i) {
|
|
|
|
restoreRect0(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 3 * _tickLength;
|
|
|
|
_screen->drawShape(0, _shapes[220+item], x, y, 0, 0);
|
|
|
|
_screen->drawShape(0, _shapes[4+i], x, y + yAdd, 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if ((nextTime - _system->getMillis()) >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
restoreRect0(x, y);
|
|
|
|
}
|
|
|
|
|
2005-12-23 17:49:14 +00:00
|
|
|
void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) {
|
|
|
|
debug(9, "magicOutMouseItem(%d, %d)", animIndex, itemPos);
|
|
|
|
int videoPageBackUp = _screen->_curPage;
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
int x = 0, y = 0;
|
|
|
|
if (itemPos == -1) {
|
|
|
|
x = _mouseX - 12;
|
|
|
|
y = _mouseY - 18;
|
|
|
|
} else {
|
|
|
|
x = _itemPosX[itemPos] - 4;
|
|
|
|
y = _itemPosY[itemPos] - 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_itemInHand == -1 && itemPos == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tableIndex = 0, loopStart = 0, maxLoops = 0;
|
|
|
|
if (animIndex == 0) {
|
|
|
|
tableIndex = _rnd.getRandomNumberRng(0, 5);
|
|
|
|
loopStart = 35;
|
|
|
|
maxLoops = 9;
|
|
|
|
} else if (animIndex == 1) {
|
|
|
|
tableIndex = _rnd.getRandomNumberRng(0, 11);
|
|
|
|
loopStart = 115;
|
|
|
|
maxLoops = 8;
|
|
|
|
} else if (animIndex == 2) {
|
|
|
|
tableIndex = 0;
|
|
|
|
loopStart = 124;
|
|
|
|
maxLoops = 4;
|
|
|
|
} else {
|
|
|
|
tableIndex = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (animIndex == 2) {
|
|
|
|
// snd_kyraPlaySound(0x5E);
|
|
|
|
} else {
|
|
|
|
// snd_kyraPlaySound(0x37);
|
|
|
|
}
|
|
|
|
_screen->hideMouse();
|
|
|
|
backUpRect1(x, y);
|
|
|
|
|
|
|
|
for (int shape = _magicMouseItemStartFrame[animIndex]; shape <= _magicMouseItemEndFrame[animIndex]; ++shape) {
|
|
|
|
restoreRect1(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 4 * _tickLength;
|
|
|
|
_screen->drawShape(0, _shapes[220+_itemInHand], x + 4, y + 3, 0, 0);
|
|
|
|
if (tableIndex == -1) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
|
|
|
|
} else {
|
|
|
|
specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if (nextTime - _system->getMillis() >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (itemPos != -1) {
|
|
|
|
restoreRect1(x, y);
|
|
|
|
_screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0);
|
|
|
|
backUpRect1(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int shape = _magicMouseItemStartFrame2[animIndex]; shape <= _magicMouseItemEndFrame2[animIndex]; ++shape) {
|
|
|
|
restoreRect1(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 4 * _tickLength;
|
|
|
|
_screen->drawShape(0, _shapes[220+_itemInHand], x + 4, y + 3, 0, 0);
|
|
|
|
if (tableIndex == -1) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
|
|
|
|
} else {
|
|
|
|
specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if (nextTime - _system->getMillis() >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
restoreRect1(x, y);
|
|
|
|
if (itemPos == -1) {
|
|
|
|
_screen->setMouseCursor(1, 1, _shapes[4]);
|
|
|
|
_itemInHand = -1;
|
|
|
|
} else {
|
|
|
|
_characterList[0].inventoryItems[itemPos] = 0xFF;
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
_screen->_curPage = videoPageBackUp;
|
|
|
|
}
|
|
|
|
|
2005-12-28 21:34:40 +00:00
|
|
|
void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) {
|
|
|
|
debug(9, "magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos);
|
|
|
|
int videoPageBackUp = _screen->_curPage;
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
int x = 0, y = 0;
|
|
|
|
if (itemPos == -1) {
|
|
|
|
x = _mouseX - 12;
|
|
|
|
y = _mouseY - 18;
|
|
|
|
} else {
|
|
|
|
x = _itemPosX[itemPos] - 4;
|
|
|
|
y = _itemPosX[itemPos] - 3;
|
|
|
|
}
|
|
|
|
if (item < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int tableIndex = -1, loopStart = 0, maxLoops = 0;
|
|
|
|
if (animIndex == 0) {
|
|
|
|
tableIndex = _rnd.getRandomNumberRng(0, 5);
|
|
|
|
loopStart = 35;
|
|
|
|
maxLoops = 9;
|
|
|
|
} else if (animIndex == 1) {
|
|
|
|
tableIndex = _rnd.getRandomNumberRng(0, 11);
|
|
|
|
loopStart = 115;
|
|
|
|
maxLoops = 8;
|
|
|
|
} else if (animIndex == 2) {
|
|
|
|
tableIndex = 0;
|
|
|
|
loopStart = 124;
|
|
|
|
maxLoops = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
_screen->hideMouse();
|
|
|
|
backUpRect1(x, y);
|
|
|
|
if (animIndex == 2) {
|
|
|
|
// snd_playSoundEffect(0x5E);
|
|
|
|
} else {
|
|
|
|
// snd_playSoundEffect(0x37);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int shape = _magicMouseItemStartFrame[animIndex]; shape <= _magicMouseItemEndFrame[animIndex]; ++shape) {
|
|
|
|
restoreRect1(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 4 * _tickLength;
|
|
|
|
if (tableIndex == -1) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
|
|
|
|
} else {
|
|
|
|
specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if (nextTime - _system->getMillis() >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int shape = _magicMouseItemStartFrame2[animIndex]; shape <= _magicMouseItemEndFrame2[animIndex]; ++shape) {
|
|
|
|
restoreRect1(x, y);
|
|
|
|
uint32 nextTime = _system->getMillis() + 4 * _tickLength;
|
|
|
|
if (tableIndex == -1) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
|
|
|
|
} else {
|
|
|
|
specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
while (_system->getMillis() < nextTime) {
|
|
|
|
if (nextTime - _system->getMillis() >= 10)
|
|
|
|
delay(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
restoreRect1(x, y);
|
|
|
|
if (itemPos == -1) {
|
|
|
|
_screen->setMouseCursor(8, 15, _shapes[220+item]);
|
|
|
|
_itemInHand = item;
|
|
|
|
} else {
|
|
|
|
_characterList[0].inventoryItems[itemPos] = item;
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->drawShape(0, _shapes[220+item], _itemPosX[itemPos], _itemPosY[itemPos], 0, 0);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
_screen->_curPage = videoPageBackUp;
|
|
|
|
}
|
|
|
|
|
2005-12-23 17:49:14 +00:00
|
|
|
void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) {
|
|
|
|
debug(9, "specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
|
|
|
|
static const uint8 table1[] = {
|
|
|
|
0x23, 0x45, 0x55, 0x72, 0x84, 0xCF, 0x00, 0x00
|
|
|
|
};
|
|
|
|
static const uint8 table2[] = {
|
|
|
|
0x73, 0xB5, 0x80, 0x21, 0x13, 0x39, 0x45, 0x55, 0x62, 0xB4, 0xCF, 0xD8
|
|
|
|
};
|
|
|
|
static const uint8 table3[] = {
|
|
|
|
0x7C, 0xD0, 0x74, 0x84, 0x87, 0x00, 0x00, 0x00
|
|
|
|
};
|
|
|
|
int tableValue = 0;
|
|
|
|
if (animIndex == 0) {
|
|
|
|
tableValue = table1[tableIndex];
|
|
|
|
} else if (animIndex == 1) {
|
|
|
|
tableValue = table2[tableIndex];
|
|
|
|
} else if (animIndex == 2) {
|
|
|
|
tableValue = table3[tableIndex];
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
processSpecialMouseItemFX(shape, x, y, tableValue, loopStart, maxLoops);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) {
|
|
|
|
debug(9, "processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops);
|
|
|
|
uint8 shapeColorTable[16];
|
|
|
|
uint8 *shapePtr = _shapes[4+shape] + 10;
|
|
|
|
if (_features & GF_TALKIE)
|
|
|
|
shapePtr += 2;
|
|
|
|
for (int i = 0; i < 16; ++i) {
|
|
|
|
shapeColorTable[i] = shapePtr[i];
|
|
|
|
}
|
|
|
|
for (int i = loopStart; i < loopStart + maxLoops; ++i) {
|
|
|
|
for (int i2 = 0; i2 < 16; ++i2) {
|
|
|
|
if (shapePtr[i2] == i) {
|
|
|
|
shapeColorTable[i2] = (i + tableValue) - loopStart;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], x, y, 0, 0x8000, shapeColorTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::updatePlayerItemsForScene() {
|
|
|
|
debug(9, "updatePlayerItemsForScene()");
|
|
|
|
if (_itemInHand >= 29 && _itemInHand < 33) {
|
|
|
|
++_itemInHand;
|
|
|
|
if (_itemInHand > 33)
|
|
|
|
_itemInHand = 33;
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->setMouseCursor(8, 15, _shapes[220+_itemInHand]);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool redraw = false;
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
uint8 item = _currentCharacter->inventoryItems[i];
|
|
|
|
if (item >= 29 && item < 33) {
|
|
|
|
++item;
|
|
|
|
if (item > 33)
|
|
|
|
item = 33;
|
|
|
|
_currentCharacter->inventoryItems[i] = item;
|
|
|
|
redraw = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (redraw) {
|
|
|
|
_screen->hideMouse();
|
|
|
|
redrawInventory(0);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_itemInHand == 33) {
|
|
|
|
magicOutMouseItem(2, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
_screen->hideMouse();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
uint8 item = _currentCharacter->inventoryItems[i];
|
|
|
|
if (item == 33) {
|
|
|
|
magicOutMouseItem(2, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::redrawInventory(int page) {
|
|
|
|
int videoPageBackUp = _screen->_curPage;
|
|
|
|
_screen->_curPage = page;
|
|
|
|
_screen->hideMouse();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
_screen->fillRect(_itemPosX[i], _itemPosY[i], _itemPosX[i] + 15, _itemPosY[i] + 15, 12, page);
|
|
|
|
if (_currentCharacter->inventoryItems[i] != 0xFF) {
|
|
|
|
uint8 item = _currentCharacter->inventoryItems[i];
|
|
|
|
_screen->drawShape(page, _shapes[220+item], _itemPosX[i], _itemPosY[i], 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
_screen->_curPage = videoPageBackUp;
|
|
|
|
_screen->updateScreen();
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
#pragma mark -
|
2005-12-26 14:53:51 +00:00
|
|
|
#pragma mark - Animation/shape specific code
|
2005-10-29 18:37:40 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2005-11-10 14:08:50 +00:00
|
|
|
void KyraEngine::preserveAllBackgrounds() {
|
|
|
|
uint8 currPage = _screen->_curPage;
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
|
|
|
|
AnimObject *curObject = _objectQueue;
|
|
|
|
while (curObject) {
|
2005-11-10 18:58:44 +00:00
|
|
|
if (curObject->active && !curObject->unk1) {
|
2005-11-10 14:08:50 +00:00
|
|
|
preserveOrRestoreBackground(curObject, false);
|
|
|
|
curObject->bkgdChangeFlag = 0;
|
|
|
|
}
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
|
|
|
_screen->_curPage = currPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::flagAllObjectsForBkgdChange() {
|
|
|
|
AnimObject *curObject = _objectQueue;
|
|
|
|
while (curObject) {
|
|
|
|
curObject->bkgdChangeFlag = 1;
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::flagAllObjectsForRefresh() {
|
|
|
|
AnimObject *curObject = _objectQueue;
|
|
|
|
while (curObject) {
|
|
|
|
curObject->refreshFlag = 1;
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
void KyraEngine::restoreAllObjectBackgrounds() {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "restoreAllObjectBackground()");
|
2005-10-29 18:37:40 +00:00
|
|
|
AnimObject *curObject = _objectQueue;
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
|
|
|
|
while (curObject) {
|
2005-12-20 10:58:07 +00:00
|
|
|
if (curObject->active && !curObject->unk1) {
|
2005-10-29 18:37:40 +00:00
|
|
|
preserveOrRestoreBackground(curObject, true);
|
|
|
|
curObject->x2 = curObject->x1;
|
|
|
|
curObject->y2 = curObject->y1;
|
|
|
|
}
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::preserveAnyChangedBackgrounds() {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "preserveAnyChangedBackgrounds()");
|
2005-10-29 18:37:40 +00:00
|
|
|
AnimObject *curObject = _objectQueue;
|
|
|
|
_screen->_curPage = 2;
|
|
|
|
|
|
|
|
while (curObject) {
|
2005-12-20 10:58:07 +00:00
|
|
|
if (curObject->active && !curObject->unk1 && curObject->bkgdChangeFlag) {
|
2005-10-29 18:37:40 +00:00
|
|
|
preserveOrRestoreBackground(curObject, false);
|
|
|
|
curObject->bkgdChangeFlag = 0;
|
|
|
|
}
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
_screen->_curPage = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::preserveOrRestoreBackground(AnimObject *obj, bool restore) {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "preserveOrRestoreBackground(0x%X, restore)", obj, restore);
|
2005-11-09 22:26:12 +00:00
|
|
|
int x = 0, y = 0, width = obj->width << 3, height = obj->height;
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
if (restore) {
|
|
|
|
x = obj->x2;
|
|
|
|
y = obj->y2;
|
|
|
|
} else {
|
|
|
|
x = obj->x1;
|
|
|
|
y = obj->y1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x < 0)
|
|
|
|
x = 0;
|
|
|
|
if (y < 0)
|
|
|
|
y = 0;
|
|
|
|
|
|
|
|
int temp;
|
|
|
|
|
|
|
|
temp = x + width;
|
|
|
|
if (temp >= 319) {
|
|
|
|
x = 319 - width;
|
|
|
|
}
|
|
|
|
temp = y + height;
|
|
|
|
if (temp >= 136) {
|
|
|
|
y = 136 - height;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (restore) {
|
|
|
|
_screen->copyBlockToPage(_screen->_curPage, x, y, width, height, obj->background);
|
2005-11-09 22:26:12 +00:00
|
|
|
} else {
|
|
|
|
_screen->copyRegionToBuffer(_screen->_curPage, x, y, width, height, obj->background);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::prepDrawAllObjects() {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "prepDrawAllObjects()");
|
2005-10-29 18:37:40 +00:00
|
|
|
AnimObject *curObject = _objectQueue;
|
|
|
|
int drawPage = 2;
|
|
|
|
int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0;
|
2005-12-24 18:00:35 +00:00
|
|
|
if (_noDrawShapesFlag)
|
|
|
|
return;
|
2005-10-29 18:37:40 +00:00
|
|
|
if (_brandonStatusBit & 0x20)
|
|
|
|
flagUnk1 = 0x200;
|
|
|
|
if (_brandonStatusBit & 0x40)
|
|
|
|
flagUnk2 = 0x4000;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
while (curObject) {
|
|
|
|
if (curObject->active) {
|
|
|
|
int xpos = curObject->x1;
|
|
|
|
int ypos = curObject->y1;
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
int drawLayer = 0;
|
|
|
|
if (!(curObject->flags & 0x800)) {
|
|
|
|
drawLayer = 7;
|
|
|
|
} else if (curObject->unk1) {
|
|
|
|
drawLayer = 0;
|
2005-10-29 18:37:40 +00:00
|
|
|
} else {
|
2005-11-18 23:55:31 +00:00
|
|
|
drawLayer = _sprites->getDrawLayer(curObject->drawY);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-10-30 19:58:51 +00:00
|
|
|
// talking head functionallity
|
2005-12-09 14:52:31 +00:00
|
|
|
if (_talkingCharNum != -1) {
|
2005-11-10 18:58:44 +00:00
|
|
|
const int16 baseAnimFrameTable1[] = { 0x11, 0x35, 0x59, 0x00, 0x00, 0x00 };
|
|
|
|
const int16 baseAnimFrameTable2[] = { 0x15, 0x39, 0x5D, 0x00, 0x00, 0x00 };
|
|
|
|
const int8 xOffsetTable1[] = { 2, 4, 0, 5, 2, 0, 0, 0 };
|
|
|
|
const int8 xOffsetTable2[] = { 6, 4, 8, 3, 6, 0, 0, 0 };
|
|
|
|
const int8 yOffsetTable1[] = { 0, 8, 1, 1, 0, 0, 0, 0 };
|
|
|
|
const int8 yOffsetTable2[] = { 0, 8, 1, 1, 0, 0, 0, 0 };
|
|
|
|
if (curObject->index == 0 || curObject->index <= 4) {
|
|
|
|
int shapesIndex = 0;
|
|
|
|
if (curObject->index == _charSayUnk3) {
|
2005-12-09 14:52:31 +00:00
|
|
|
shapesIndex = _currHeadShape + baseAnimFrameTable1[curObject->index];
|
2005-11-10 18:58:44 +00:00
|
|
|
} else {
|
|
|
|
shapesIndex = baseAnimFrameTable2[curObject->index];
|
|
|
|
int temp2 = 0;
|
|
|
|
if (curObject->index == 2) {
|
|
|
|
if (_characterList[2].sceneId == 0x4D || _characterList[2].sceneId == 0x56) {
|
|
|
|
temp2 = 1;
|
|
|
|
} else {
|
|
|
|
temp2 = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
temp2 = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!temp2) {
|
|
|
|
shapesIndex = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
xpos = curObject->x1;
|
|
|
|
ypos = curObject->y1;
|
|
|
|
|
|
|
|
int tempX = 0, tempY = 0;
|
|
|
|
if (curObject->flags & 0x1) {
|
|
|
|
tempX = (xOffsetTable1[curObject->index] * _brandonScaleX) >> 8;
|
|
|
|
tempY = yOffsetTable1[curObject->index];
|
|
|
|
} else {
|
|
|
|
tempX = (xOffsetTable2[curObject->index] * _brandonScaleX) >> 8;
|
|
|
|
tempY = yOffsetTable2[curObject->index];
|
|
|
|
}
|
|
|
|
tempY = (tempY * _brandonScaleY) >> 8;
|
|
|
|
xpos += tempX;
|
|
|
|
ypos += tempY;
|
|
|
|
|
|
|
|
if (_scaleMode && _brandonScaleX != 256) {
|
|
|
|
++xpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (curObject->index == 0) {
|
|
|
|
if (!(_brandonStatusBit & 2)) {
|
|
|
|
flagUnk3 = 0x100;
|
|
|
|
if ((flagUnk1 & 0x200) || (flagUnk2 & 0x4000)) {
|
|
|
|
flagUnk3 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int tempFlags = 0;
|
|
|
|
if (flagUnk3 & 0x100) {
|
|
|
|
if (curObject->flags & 1) {
|
|
|
|
tempFlags = 1;
|
|
|
|
}
|
|
|
|
tempFlags |= 0x800 | flagUnk1 | 0x100;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flagUnk3 & 0x100) && (flagUnk2 & 0x4000)) {
|
|
|
|
tempFlags = 0;
|
|
|
|
if (curObject->flags & 1) {
|
|
|
|
tempFlags = 1;
|
|
|
|
}
|
|
|
|
tempFlags |= 0x900 | flagUnk1 | 0x4000;
|
2005-12-28 21:34:40 +00:00
|
|
|
_screen->drawShape(drawPage, _shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 4, _brandonPoisonFlagsGFX, int(1), int(0)/*XXX*/, drawLayer, _brandonScaleX, _brandonScaleY);
|
2005-11-10 18:58:44 +00:00
|
|
|
} else {
|
|
|
|
if (!(flagUnk2 & 0x4000)) {
|
|
|
|
tempFlags = 0;
|
|
|
|
if (curObject->flags & 1) {
|
|
|
|
tempFlags = 1;
|
|
|
|
}
|
|
|
|
tempFlags |= 0x900 | flagUnk1;
|
|
|
|
}
|
|
|
|
|
2005-12-28 21:34:40 +00:00
|
|
|
_screen->drawShape(drawPage, _shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 4, _brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
|
2005-11-10 18:58:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (shapesIndex != -1) {
|
|
|
|
int tempFlags = 0;
|
|
|
|
if (curObject->flags & 1) {
|
|
|
|
tempFlags = 1;
|
|
|
|
}
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->drawShape(drawPage, _shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 0x800, drawLayer);
|
2005-11-10 18:58:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
2005-11-10 18:58:44 +00:00
|
|
|
xpos = curObject->x1;
|
|
|
|
ypos = curObject->y1;
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
curObject->flags |= 0x800;
|
|
|
|
if (curObject->index == 0) {
|
|
|
|
flagUnk3 = 0x100;
|
|
|
|
|
|
|
|
if (flagUnk1 & 0x200 || flagUnk2 & 0x4000) {
|
|
|
|
flagUnk3 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_brandonStatusBit & 2) {
|
|
|
|
curObject->flags &= 0xFFFFFFFE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_scaleMode) {
|
|
|
|
if (flagUnk3 & 0x100) {
|
2005-12-29 22:18:40 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x100, (uint8*)_brandonPoisonFlagsGFX, int(1), drawLayer);
|
2005-10-29 18:37:40 +00:00
|
|
|
} else if (flagUnk3 & 0x4000) {
|
2005-12-29 22:18:40 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4000, _brandonInvFlag, drawLayer);
|
2005-10-29 18:37:40 +00:00
|
|
|
} else {
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1, drawLayer);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (flagUnk3 & 0x100) {
|
2005-12-29 22:18:40 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x104, (uint8*)_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
|
2005-10-29 18:37:40 +00:00
|
|
|
} else if (flagUnk3 & 0x4000) {
|
2005-12-29 22:18:40 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4004, int(0), drawLayer, _brandonInvFlag, _brandonScaleX, _brandonScaleY);
|
2005-10-29 18:37:40 +00:00
|
|
|
} else {
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4, drawLayer, _brandonScaleX, _brandonScaleY);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (curObject->index >= 16 && curObject->index <= 27) {
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | 4, drawLayer, (int)_scaleTable[curObject->drawY], (int)_scaleTable[curObject->drawY]);
|
2005-10-29 18:37:40 +00:00
|
|
|
} else {
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags, drawLayer);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::copyChangedObjectsForward(int refreshFlag) {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "copyChangedObjectsForward(%d)", refreshFlag);
|
2005-10-29 18:37:40 +00:00
|
|
|
AnimObject *curObject = _objectQueue;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
while (curObject) {
|
|
|
|
if (curObject->active) {
|
|
|
|
if (curObject->refreshFlag || refreshFlag) {
|
|
|
|
int xpos = 0, ypos = 0, width = 0, height = 0;
|
2005-11-09 22:26:12 +00:00
|
|
|
xpos = curObject->x1 - (curObject->width2+1);
|
|
|
|
ypos = curObject->y1 - curObject->height2;
|
2005-12-20 10:58:07 +00:00
|
|
|
width = (curObject->width + ((curObject->width2)>>3)+2)<<3;
|
2005-11-09 22:26:12 +00:00
|
|
|
height = curObject->height + curObject->height2*2;
|
2005-10-29 18:37:40 +00:00
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
if (xpos < 8) {
|
|
|
|
xpos = 8;
|
|
|
|
} else if (xpos + width > 312) {
|
|
|
|
width = 312 - xpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ypos < 8) {
|
|
|
|
ypos = 8;
|
2005-12-08 17:19:18 +00:00
|
|
|
} else if (ypos + height > 136) {
|
|
|
|
height = 136 - ypos;
|
2005-11-13 19:35:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_screen->copyRegion(xpos, ypos, xpos, ypos, width, height, 2, 0, Screen::CR_CLIPPED);
|
2005-10-29 18:37:40 +00:00
|
|
|
curObject->refreshFlag = 0;
|
2005-12-10 17:51:40 +00:00
|
|
|
_updateScreen = true;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
curObject = curObject->nextAnimObject;
|
|
|
|
}
|
2005-12-10 17:51:40 +00:00
|
|
|
if (_updateScreen) {
|
2005-11-11 22:17:06 +00:00
|
|
|
_screen->updateScreen();
|
2005-12-10 17:51:40 +00:00
|
|
|
_updateScreen = false;
|
|
|
|
}
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::updateAllObjectShapes() {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "updateAllObjectShapes()");
|
2005-10-29 18:37:40 +00:00
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
prepDrawAllObjects();
|
|
|
|
copyChangedObjectsForward(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::animRefreshNPC(int character) {
|
2005-11-01 14:19:50 +00:00
|
|
|
debug(9, "animRefreshNPC(%d)", character);
|
2005-10-29 18:37:40 +00:00
|
|
|
AnimObject *animObj = &_charactersAnimState[character];
|
|
|
|
Character *ch = &_characterList[character];
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
animObj->refreshFlag = 1;
|
|
|
|
animObj->bkgdChangeFlag = 1;
|
|
|
|
int facing = ch->facing;
|
|
|
|
if (facing >= 1 && facing <= 3) {
|
2005-11-09 22:26:12 +00:00
|
|
|
animObj->flags |= 1;
|
2005-10-29 18:37:40 +00:00
|
|
|
} else if (facing >= 5 && facing <= 7) {
|
2005-11-09 22:26:12 +00:00
|
|
|
animObj->flags &= 0xFFFFFFFE;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
animObj->drawY = ch->y1;
|
|
|
|
animObj->sceneAnimPtr = _shapes[4+ch->currentAnimFrame];
|
|
|
|
animObj->animFrameNumber = ch->currentAnimFrame;
|
|
|
|
if (character == 0) {
|
|
|
|
if (_brandonStatusBit & 10) {
|
|
|
|
animObj->animFrameNumber = 88;
|
|
|
|
ch->currentAnimFrame = 88;
|
|
|
|
}
|
|
|
|
if (_brandonStatusBit & 2) {
|
|
|
|
animObj->animFrameNumber = _brandonDrawFrame;
|
|
|
|
ch->currentAnimFrame = _brandonDrawFrame;
|
|
|
|
animObj->sceneAnimPtr = _shapes[4+_brandonDrawFrame];
|
2005-12-29 22:18:40 +00:00
|
|
|
if (_brandonStatusBit0x02Flag) {
|
|
|
|
++_brandonDrawFrame;
|
|
|
|
if (_brandonDrawFrame >= 122)
|
|
|
|
_brandonDrawFrame = 113;
|
|
|
|
_brandonStatusBit0x02Flag = 0;
|
|
|
|
}
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
int xOffset = _defaultShapeTable[ch->currentAnimFrame-7].xOffset;
|
|
|
|
int yOffset = _defaultShapeTable[ch->currentAnimFrame-7].yOffset;
|
2005-10-29 18:37:40 +00:00
|
|
|
|
|
|
|
if (_scaleMode) {
|
|
|
|
animObj->x1 = ch->x1;
|
|
|
|
animObj->y1 = ch->y1;
|
|
|
|
|
|
|
|
_brandonScaleX = _scaleTable[ch->y1];
|
|
|
|
_brandonScaleY = _scaleTable[ch->y1];
|
2005-11-09 22:26:12 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
animObj->x1 += (_brandonScaleX * xOffset) >> 8;
|
|
|
|
animObj->y1 += (_brandonScaleY * yOffset) >> 8;
|
|
|
|
} else {
|
2005-11-09 22:26:12 +00:00
|
|
|
animObj->x1 = ch->x1 + xOffset;
|
|
|
|
animObj->y1 = ch->y1 + yOffset;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
animObj->width2 = 4;
|
|
|
|
animObj->height2 = 3;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
_objectQueue = objectRemoveQueue(_objectQueue, animObj);
|
|
|
|
if (_objectQueue) {
|
2005-11-10 14:08:50 +00:00
|
|
|
_objectQueue = objectQueue(_objectQueue, animObj);
|
2005-10-29 18:37:40 +00:00
|
|
|
} else {
|
2005-11-10 14:08:50 +00:00
|
|
|
_objectQueue = objectAddHead(0, animObj);
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
void KyraEngine::animRemoveGameItem(int index) {
|
|
|
|
debug(9, "animRemoveGameItem(%d)", index);
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
|
|
|
|
AnimObject *animObj = &_animItems[index];
|
|
|
|
animObj->sceneAnimPtr = 0;
|
|
|
|
animObj->animFrameNumber = -1;
|
|
|
|
animObj->refreshFlag = 1;
|
|
|
|
animObj->bkgdChangeFlag = 1;
|
|
|
|
updateAllObjectShapes();
|
|
|
|
animObj->active = 0;
|
|
|
|
|
|
|
|
objectRemoveQueue(_objectQueue, animObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::animAddGameItem(int index, uint16 sceneId) {
|
|
|
|
debug(9, "animRemoveGameItem(%d, %d)", index, sceneId);
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
assert(sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[sceneId];
|
|
|
|
AnimObject *animObj = &_animItems[index];
|
|
|
|
animObj->active = 1;
|
|
|
|
animObj->refreshFlag = 1;
|
|
|
|
animObj->bkgdChangeFlag = 1;
|
|
|
|
animObj->drawY = currentRoom->itemsYPos[index];
|
|
|
|
animObj->sceneAnimPtr = _shapes[220+currentRoom->itemsTable[index]];
|
|
|
|
animObj->animFrameNumber = -1;
|
|
|
|
animObj->x1 = currentRoom->itemsXPos[index];
|
|
|
|
animObj->y1 = currentRoom->itemsYPos[index];
|
|
|
|
animObj->x1 -= fetchAnimWidth(animObj->sceneAnimPtr, _scaleTable[animObj->drawY]) >> 1;
|
|
|
|
animObj->y1 -= fetchAnimHeight(animObj->sceneAnimPtr, _scaleTable[animObj->drawY]);
|
|
|
|
animObj->x2 = animObj->x1;
|
|
|
|
animObj->y2 = animObj->y1;
|
|
|
|
animObj->width2 = 0;
|
|
|
|
animObj->height2 = 0;
|
|
|
|
_objectQueue = objectQueue(_objectQueue, animObj);
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
animObj->refreshFlag = 1;
|
|
|
|
animObj->bkgdChangeFlag = 1;
|
|
|
|
}
|
|
|
|
|
2005-12-09 23:02:16 +00:00
|
|
|
void KyraEngine::animAddNPC(int character) {
|
|
|
|
debug(9, "animAddNPC(%d)", character);
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
AnimObject *animObj = &_charactersAnimState[character];
|
|
|
|
const Character *ch = &_characterList[character];
|
|
|
|
|
|
|
|
animObj->active = 1;
|
|
|
|
animObj->refreshFlag = 1;
|
|
|
|
animObj->bkgdChangeFlag = 1;
|
|
|
|
animObj->drawY = ch->y1;
|
|
|
|
animObj->sceneAnimPtr = _shapes[4+ch->currentAnimFrame];
|
|
|
|
animObj->x1 = animObj->x2 = ch->x1 + _defaultShapeTable[ch->currentAnimFrame-7].xOffset;
|
|
|
|
animObj->y1 = animObj->y2 = ch->y1 + _defaultShapeTable[ch->currentAnimFrame-7].yOffset;
|
|
|
|
if (ch->facing >= 1 && ch->facing <= 3) {
|
|
|
|
animObj->flags |= 1;
|
|
|
|
} else if (ch->facing >= 5 && ch->facing <= 7) {
|
|
|
|
animObj->flags &= 0xFFFFFFFE;
|
|
|
|
}
|
|
|
|
_objectQueue = objectQueue(_objectQueue, animObj);
|
|
|
|
preserveAnyChangedBackgrounds();
|
|
|
|
animObj->refreshFlag = 1;
|
|
|
|
animObj->bkgdChangeFlag = 1;
|
|
|
|
}
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
void KyraEngine::drawJewelPress(int jewel, int drawSpecial) {
|
|
|
|
debug(9, "drawJewelPress(%d, %d)", jewel, drawSpecial);
|
|
|
|
_screen->hideMouse();
|
|
|
|
int shape = 0;
|
|
|
|
if (drawSpecial) {
|
|
|
|
shape = 0x14E;
|
|
|
|
} else {
|
|
|
|
shape = jewel + 0x149;
|
|
|
|
}
|
|
|
|
// snd_playSoundEffect(0x45);
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
delayWithTicks(2);
|
|
|
|
if (drawSpecial) {
|
|
|
|
shape = 0x148;
|
|
|
|
} else {
|
|
|
|
shape = jewel + 0x143;
|
|
|
|
}
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::drawJewelsFadeOutStart() {
|
|
|
|
debug(9, "drawJewelsFadeOutStart()");
|
|
|
|
static const uint16 jewelTable1[] = { 0x164, 0x15F, 0x15A, 0x155, 0x150, 0xFFFF };
|
|
|
|
static const uint16 jewelTable2[] = { 0x163, 0x15E, 0x159, 0x154, 0x14F, 0xFFFF };
|
|
|
|
static const uint16 jewelTable3[] = { 0x166, 0x160, 0x15C, 0x157, 0x152, 0xFFFF };
|
|
|
|
static const uint16 jewelTable4[] = { 0x165, 0x161, 0x15B, 0x156, 0x151, 0xFFFF };
|
|
|
|
for (int i = 0; jewelTable1[i] != 0xFFFF; ++i) {
|
|
|
|
if (queryGameFlag(0x57)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+jewelTable1[i]], _amuletX2[2], _amuletY2[2], 0, 0);
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0x59)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+jewelTable3[i]], _amuletX2[4], _amuletY2[4], 0, 0);
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0x56)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+jewelTable2[i]], _amuletX2[1], _amuletY2[1], 0, 0);
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0x58)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+jewelTable4[i]], _amuletX2[3], _amuletY2[3], 0, 0);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
delayWithTicks(3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::drawJewelsFadeOutEnd(int jewel) {
|
|
|
|
debug(9, "drawJewelsFadeOutEnd(%d)", jewel);
|
|
|
|
static const uint16 jewelTable[] = { 0x153, 0x158, 0x15D, 0x162, 0x148, 0xFFFF };
|
|
|
|
int newDelay = 0;
|
|
|
|
switch (jewel-1) {
|
|
|
|
case 2:
|
|
|
|
if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
|
|
|
|
newDelay = 18900;
|
|
|
|
} else {
|
|
|
|
newDelay = 8100;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
newDelay = 3600;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
setGameFlag(0xF1);
|
|
|
|
setTimerCountdown(19, newDelay);
|
|
|
|
_screen->hideMouse();
|
|
|
|
for (int i = 0; jewelTable[i] != 0xFFFF; ++i) {
|
|
|
|
uint16 shape = jewelTable[i];
|
|
|
|
if (queryGameFlag(0x57)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], _amuletX2[2], _amuletY2[2], 0, 0);
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0x59)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], _amuletX2[4], _amuletY2[4], 0, 0);
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0x56)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], _amuletX2[1], _amuletY2[1], 0, 0);
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0x58)) {
|
|
|
|
_screen->drawShape(0, _shapes[4+shape], _amuletX2[3], _amuletY2[3], 0, 0);
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
delayWithTicks(3);
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setupShapes123(const Shape *shapeTable, int endShape, int flags) {
|
|
|
|
debug(9, "setupShapes123(0x%X, startShape, flags)", shapeTable, endShape, flags);
|
|
|
|
for (int i = 123; i <= 172; ++i) {
|
|
|
|
_shapes[4+i] = NULL;
|
|
|
|
}
|
|
|
|
uint8 curImage = 0xFF;
|
|
|
|
int curPageBackUp = _screen->_curPage;
|
|
|
|
_screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff
|
|
|
|
int shapeFlags = 2;
|
|
|
|
if (flags)
|
|
|
|
shapeFlags = 3;
|
|
|
|
for (int i = 123; i < 123+endShape; ++i) {
|
|
|
|
uint8 newImage = shapeTable[i-123].imageIndex;
|
2005-12-29 22:18:40 +00:00
|
|
|
if (newImage != curImage && newImage != 0xFF) {
|
2005-12-26 14:53:51 +00:00
|
|
|
assert(_characterImageTable);
|
|
|
|
loadBitmap(_characterImageTable[newImage], 8, 8, 0);
|
|
|
|
curImage = newImage;
|
|
|
|
}
|
2005-12-29 22:18:40 +00:00
|
|
|
_shapes[4+i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags);
|
2005-12-26 14:53:51 +00:00
|
|
|
assert(i-7 < _defaultShapeTableSize);
|
|
|
|
_defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset;
|
|
|
|
_defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset;
|
|
|
|
_defaultShapeTable[i-7].w = shapeTable[i-123].w;
|
|
|
|
_defaultShapeTable[i-7].h = shapeTable[i-123].h;
|
|
|
|
}
|
|
|
|
_screen->_curPage = curPageBackUp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::freeShapes123() {
|
|
|
|
debug(9, "freeShapes123()");
|
|
|
|
for (int i = 123; i <= 172; ++i) {
|
|
|
|
free(_shapes[4+i]);
|
|
|
|
_shapes[4+i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::setBrandonAnimSeqSize(int width, int height) {
|
|
|
|
debug(9, "setBrandonAnimSeqSize(%d, %d)", width, height);
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
_brandonAnimSeqSizeWidth = _charactersAnimState[0].width;
|
|
|
|
_brandonAnimSeqSizeHeight = _charactersAnimState[0].height;
|
|
|
|
_charactersAnimState[0].width = width + 1;
|
|
|
|
_charactersAnimState[0].height = height;
|
|
|
|
preserveAllBackgrounds();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::resetBrandonAnimSeqSize() {
|
|
|
|
restoreAllObjectBackgrounds();
|
|
|
|
_charactersAnimState[0].width = _brandonAnimSeqSizeWidth;
|
|
|
|
_charactersAnimState[0].height = _brandonAnimSeqSizeHeight;
|
|
|
|
preserveAllBackgrounds();
|
|
|
|
}
|
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Queue handling
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
AnimObject *KyraEngine::objectRemoveQueue(AnimObject *queue, AnimObject *rem) {
|
|
|
|
AnimObject *cur = queue;
|
|
|
|
AnimObject *prev = queue;
|
2005-11-10 14:08:50 +00:00
|
|
|
|
2005-10-29 18:37:40 +00:00
|
|
|
while (cur != rem && cur) {
|
|
|
|
AnimObject *temp = cur->nextAnimObject;
|
|
|
|
if (!temp)
|
|
|
|
break;
|
|
|
|
prev = cur;
|
|
|
|
cur = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cur == queue) {
|
|
|
|
if (!cur)
|
|
|
|
return 0;
|
|
|
|
return cur->nextAnimObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cur->nextAnimObject) {
|
2005-11-10 14:08:50 +00:00
|
|
|
if (cur == rem) {
|
|
|
|
if (!prev) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
prev->nextAnimObject = 0;
|
|
|
|
}
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (cur == rem) {
|
|
|
|
prev->nextAnimObject = rem->nextAnimObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
AnimObject *KyraEngine::objectAddHead(AnimObject *queue, AnimObject *head) {
|
|
|
|
head->nextAnimObject = queue;
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
|
|
|
AnimObject *KyraEngine::objectQueue(AnimObject *queue, AnimObject *add) {
|
|
|
|
if (add->drawY <= queue->drawY || !queue) {
|
|
|
|
add->nextAnimObject = queue;
|
|
|
|
return add;
|
|
|
|
}
|
|
|
|
AnimObject *cur = queue;
|
|
|
|
AnimObject *prev = queue;
|
|
|
|
while (add->drawY > cur->drawY) {
|
|
|
|
AnimObject *temp = cur->nextAnimObject;
|
|
|
|
if (!temp)
|
|
|
|
break;
|
|
|
|
prev = cur;
|
|
|
|
cur = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (add->drawY <= cur->drawY) {
|
|
|
|
prev->nextAnimObject = add;
|
|
|
|
add->nextAnimObject = cur;
|
|
|
|
} else {
|
|
|
|
cur->nextAnimObject = add;
|
|
|
|
add->nextAnimObject = 0;
|
|
|
|
}
|
2005-11-10 14:08:50 +00:00
|
|
|
return queue;
|
2005-10-29 18:37:40 +00:00
|
|
|
}
|
2005-10-30 19:58:51 +00:00
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Misc stuff
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
int16 KyraEngine::fetchAnimWidth(const uint8 *shape, int16 mult) {
|
2005-11-09 22:26:12 +00:00
|
|
|
debug(9, "fetchAnimWidth(0x%X, %d)", shape, mult);
|
2005-10-30 19:58:51 +00:00
|
|
|
if (_features & GF_TALKIE)
|
|
|
|
shape += 2;
|
2005-12-08 17:19:18 +00:00
|
|
|
return (((int16)READ_LE_UINT16((shape+3))) * mult) >> 8;
|
2005-10-30 19:58:51 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
int16 KyraEngine::fetchAnimHeight(const uint8 *shape, int16 mult) {
|
2005-11-09 22:26:12 +00:00
|
|
|
debug(9, "fetchAnimHeight(0x%X, %d)", shape, mult);
|
2005-10-30 19:58:51 +00:00
|
|
|
if (_features & GF_TALKIE)
|
|
|
|
shape += 2;
|
2005-12-08 17:19:18 +00:00
|
|
|
return (int16)(((int8)*(shape+2)) * mult) >> 8;
|
|
|
|
}
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
void KyraEngine::rectClip(int &x, int &y, int w, int h) {
|
|
|
|
if (x < 0) {
|
|
|
|
x = 0;
|
|
|
|
} else if (x + w >= 320) {
|
|
|
|
x = 320 - w;
|
|
|
|
}
|
|
|
|
if (y < 0) {
|
|
|
|
y = 0;
|
|
|
|
} else if (y + h >= 200) {
|
|
|
|
y = 200 - h;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
void KyraEngine::backUpRect0(int xpos, int ypos) {
|
|
|
|
debug(9, "backUpRect0(%d, %d)", xpos, ypos);
|
2005-12-09 19:49:47 +00:00
|
|
|
rectClip(xpos, ypos, 3<<3, 24);
|
|
|
|
_screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 3<<3, 24, _shapes[0]);
|
2005-12-08 17:19:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::restoreRect0(int xpos, int ypos) {
|
|
|
|
debug(9, "restoreRect0(%d, %d)", xpos, ypos);
|
2005-12-09 19:49:47 +00:00
|
|
|
rectClip(xpos, ypos, 3<<3, 24);
|
|
|
|
_screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 3<<3, 24, _shapes[0]);
|
2005-10-30 19:58:51 +00:00
|
|
|
}
|
2005-11-01 14:19:50 +00:00
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
void KyraEngine::backUpRect1(int xpos, int ypos) {
|
|
|
|
debug(9, "backUpRect1(%d, %d)", xpos, ypos);
|
2005-12-09 19:49:47 +00:00
|
|
|
rectClip(xpos, ypos, 4<<3, 32);
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 4<<3, 32, _shapes[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::restoreRect1(int xpos, int ypos) {
|
|
|
|
debug(9, "restoreRect1(%d, %d)", xpos, ypos);
|
2005-12-09 19:49:47 +00:00
|
|
|
rectClip(xpos, ypos, 4<<3, 32);
|
2005-11-18 23:55:31 +00:00
|
|
|
_screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _shapes[1]);
|
|
|
|
}
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
int KyraEngine::getDrawLayer(int x, int y) {
|
|
|
|
debug(9, "getDrawLayer(%d, %d)", x, y);
|
|
|
|
int xpos = x - 8;
|
|
|
|
int ypos = y - 1;
|
|
|
|
int layer = 1;
|
|
|
|
for (int curX = xpos; curX < xpos + 16; ++curX) {
|
|
|
|
int tempLayer = _screen->getShapeFlag2(curX, ypos);
|
|
|
|
if (layer < tempLayer) {
|
|
|
|
layer = tempLayer;
|
|
|
|
}
|
|
|
|
if (layer >= 7) {
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::getDrawLayer2(int x, int y, int height) {
|
|
|
|
debug(9, "getDrawLayer2(%d, %d, %d)", x, y, height);
|
|
|
|
int xpos = x - 8;
|
|
|
|
int ypos = y - 1;
|
|
|
|
int layer = 1;
|
|
|
|
|
|
|
|
for (int useX = xpos; useX < xpos + 16; ++useX) {
|
2005-12-09 19:49:47 +00:00
|
|
|
for (int useY = ypos - height; useY < ypos; ++useY) {
|
2005-12-08 17:19:18 +00:00
|
|
|
int tempLayer = _screen->getShapeFlag2(useX, useY);
|
|
|
|
if (tempLayer > layer) {
|
|
|
|
layer = tempLayer;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tempLayer >= 7) {
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
2005-12-10 15:52:38 +00:00
|
|
|
void KyraEngine::copyBackgroundBlock(int x, int page, int flag) {
|
|
|
|
debug(9, "copyBackgroundBlock(%d, %d, %d)", x, page, flag);
|
|
|
|
|
|
|
|
if (x < 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int height = 128;
|
|
|
|
if (flag)
|
|
|
|
height += 8;
|
|
|
|
if (!(x & 1))
|
|
|
|
++x;
|
|
|
|
if (x == 19)
|
|
|
|
x = 17;
|
|
|
|
uint8 *ptr1 = _unkPtr1;
|
|
|
|
uint8 *ptr2 = _unkPtr2;
|
|
|
|
int oldVideoPage = _screen->_curPage;
|
|
|
|
_screen->_curPage = page;
|
|
|
|
|
|
|
|
int curX = x;
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->copyRegionToBuffer(_screen->_curPage, 8, 8, 8, height, ptr2);
|
|
|
|
for (int i = 0; i < 19; ++i) {
|
|
|
|
int tempX = curX + 1;
|
|
|
|
_screen->copyRegionToBuffer(_screen->_curPage, tempX<<3, 8, 8, height, ptr1);
|
|
|
|
_screen->copyBlockToPage(_screen->_curPage, tempX<<3, 8, 8, height, ptr2);
|
|
|
|
int newXPos = curX + x;
|
|
|
|
if (newXPos > 37) {
|
|
|
|
newXPos = newXPos % 38;
|
|
|
|
}
|
|
|
|
tempX = newXPos + 1;
|
|
|
|
_screen->copyRegionToBuffer(_screen->_curPage, tempX<<3, 8, 8, height, ptr2);
|
|
|
|
_screen->copyBlockToPage(_screen->_curPage, tempX<<3, 8, 8, height, ptr1);
|
|
|
|
curX += x*2;
|
|
|
|
if (curX > 37) {
|
|
|
|
curX = curX % 38;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
_screen->_curPage = oldVideoPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::copyBackgroundBlock2(int x) {
|
|
|
|
copyBackgroundBlock(x, 4, 1);
|
|
|
|
}
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
void KyraEngine::makeBrandonFaceMouse() {
|
|
|
|
debug(9, "makeBrandonFaceMouse()");
|
|
|
|
if (_mouseX >= _currentCharacter->x1) {
|
|
|
|
_currentCharacter->facing = 3;
|
|
|
|
} else {
|
|
|
|
_currentCharacter->facing = 5;
|
|
|
|
}
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
}
|
|
|
|
|
2005-12-28 21:34:40 +00:00
|
|
|
void KyraEngine::setBrandonPoisonFlags(int reset) {
|
|
|
|
debug(9, "setBrandonPoisonFlags(%d)", reset);
|
|
|
|
_brandonStatusBit |= 1;
|
|
|
|
if (reset)
|
|
|
|
_poisonDeathCounter = 0;
|
|
|
|
for (int i = 0; i < 0x100; ++i) {
|
|
|
|
_brandonPoisonFlagsGFX[i] = i;
|
|
|
|
}
|
|
|
|
_brandonPoisonFlagsGFX[0x99] = 0x34;
|
|
|
|
_brandonPoisonFlagsGFX[0x9A] = 0x35;
|
|
|
|
_brandonPoisonFlagsGFX[0x9B] = 0x37;
|
|
|
|
_brandonPoisonFlagsGFX[0x9C] = 0x38;
|
|
|
|
_brandonPoisonFlagsGFX[0x9D] = 0x2B;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::resetBrandonPoisonFlags() {
|
|
|
|
debug(9, "resetBrandonPoisonFlags()");
|
|
|
|
_brandonStatusBit = 0;
|
|
|
|
for (int i = 0; i < 0x100; ++i) {
|
|
|
|
_brandonPoisonFlagsGFX[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-01 14:19:50 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Pathfinder
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
|
|
|
|
debug(9, "findWay(%d, %d, %d, %d, 0x%X, %d)", x, y, toX, toY, moveTable, moveTableSize);
|
|
|
|
x &= 0xFFFC; toX &= 0xFFFC;
|
|
|
|
y &= 0xFFFE; toY &= 0xFFFE;
|
2005-12-09 23:02:16 +00:00
|
|
|
x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY;
|
2005-11-01 14:19:50 +00:00
|
|
|
|
|
|
|
if (x == toY && y == toY) {
|
|
|
|
moveTable[0] = 8;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int curX = x;
|
|
|
|
int curY = y;
|
|
|
|
int lastUsedEntry = 0;
|
|
|
|
int tempValue = 0;
|
|
|
|
int *pathTable1 = new int[0x7D0];
|
|
|
|
int *pathTable2 = new int[0x7D0];
|
2005-11-10 21:42:42 +00:00
|
|
|
assert(pathTable1 && pathTable2);
|
2005-11-01 14:19:50 +00:00
|
|
|
|
|
|
|
while (true) {
|
|
|
|
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
|
|
|
|
changePosTowardsFacing(curX, curY, newFacing);
|
|
|
|
|
|
|
|
if (curX == toX && curY == toY) {
|
|
|
|
if (!lineIsPassable(curX, curY))
|
|
|
|
break;
|
|
|
|
moveTable[lastUsedEntry++] = newFacing;
|
|
|
|
break;
|
2005-11-10 21:42:42 +00:00
|
|
|
}
|
2005-11-01 14:19:50 +00:00
|
|
|
|
|
|
|
if (lineIsPassable(curX, curY)) {
|
|
|
|
if (lastUsedEntry == moveTableSize) {
|
|
|
|
delete [] pathTable1;
|
|
|
|
delete [] pathTable2;
|
|
|
|
return 0x7D00;
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
// debug drawing
|
|
|
|
//if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
|
|
|
|
// _screen->setPagePixel(0, curX, curY, 11);
|
|
|
|
// _screen->updateScreen();
|
|
|
|
// waitTicks(5);
|
|
|
|
//}
|
2005-11-01 14:19:50 +00:00
|
|
|
moveTable[lastUsedEntry++] = newFacing;
|
|
|
|
x = curX;
|
|
|
|
y = curY;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int temp = 0;
|
|
|
|
while (true) {
|
|
|
|
newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
|
|
|
|
changePosTowardsFacing(curX, curY, newFacing);
|
2005-11-09 22:26:12 +00:00
|
|
|
// debug drawing
|
|
|
|
//if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
|
|
|
|
// _screen->setPagePixel(0, curX, curY, 8);
|
|
|
|
// _screen->updateScreen();
|
|
|
|
// waitTicks(5);
|
|
|
|
//}
|
2005-11-01 14:19:50 +00:00
|
|
|
|
|
|
|
if (!lineIsPassable(curX, curY)) {
|
|
|
|
if (curX != toX || curY != toY)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (curX == toX && curY == toY) {
|
|
|
|
if (!lineIsPassable(curX, curY)) {
|
|
|
|
tempValue = 0;
|
|
|
|
temp = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0);
|
|
|
|
tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0);
|
|
|
|
if (curX == toX && curY == toY) {
|
|
|
|
if (temp == 0x7D00 && tempValue == 0x7D00) {
|
|
|
|
delete [] pathTable1;
|
|
|
|
delete [] pathTable2;
|
|
|
|
return 0x7D00;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
if (temp != 0x7D00 || tempValue != 0x7D00) {
|
2005-11-01 14:19:50 +00:00
|
|
|
break;
|
2005-11-09 22:26:12 +00:00
|
|
|
}
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (temp < tempValue) {
|
|
|
|
if (lastUsedEntry + temp > moveTableSize) {
|
|
|
|
delete [] pathTable1;
|
|
|
|
delete [] pathTable2;
|
|
|
|
return 0x7D00;
|
|
|
|
}
|
2005-11-26 16:37:20 +00:00
|
|
|
memcpy(&moveTable[lastUsedEntry], pathTable1, temp*sizeof(int));
|
2005-11-01 14:19:50 +00:00
|
|
|
lastUsedEntry += temp;
|
|
|
|
} else {
|
|
|
|
if (lastUsedEntry + tempValue > moveTableSize) {
|
|
|
|
delete [] pathTable1;
|
|
|
|
delete [] pathTable2;
|
|
|
|
return 0x7D00;
|
|
|
|
}
|
2005-11-26 16:37:20 +00:00
|
|
|
memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue*sizeof(int));
|
2005-11-09 22:26:12 +00:00
|
|
|
lastUsedEntry += tempValue;
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
x = curX;
|
|
|
|
y = curY;
|
|
|
|
if (curX == toX && curY == toY) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete [] pathTable1;
|
|
|
|
delete [] pathTable2;
|
2005-11-10 21:42:42 +00:00
|
|
|
moveTable[lastUsedEntry] = 8;
|
2005-11-01 14:19:50 +00:00
|
|
|
return getMoveTableSize(moveTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
|
|
|
|
debug(9, "findSubPath(%d, %d, %d, %d, 0x%X, %d, %d)", x, y, toX, toY, moveTable, start, end);
|
2005-11-09 22:26:12 +00:00
|
|
|
// only used for debug specific code
|
|
|
|
//static uint16 unkTable[] = { 8, 5 };
|
2005-11-01 14:19:50 +00:00
|
|
|
static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 };
|
|
|
|
static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 };
|
|
|
|
static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 };
|
2005-11-26 16:37:20 +00:00
|
|
|
static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 };
|
|
|
|
static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 };
|
2005-11-01 14:19:50 +00:00
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
// debug specific
|
2005-11-10 21:42:42 +00:00
|
|
|
//++unkTable[start];
|
2005-11-09 22:26:12 +00:00
|
|
|
//while (_screen->getPalette(0)[unkTable[start]] != 0x0F) {
|
|
|
|
// ++unkTable[start];
|
|
|
|
//}
|
2005-11-01 14:19:50 +00:00
|
|
|
|
|
|
|
int xpos1 = x, xpos2 = x;
|
|
|
|
int ypos1 = y, ypos2 = y;
|
|
|
|
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
|
|
|
|
int position = 0;
|
|
|
|
|
|
|
|
while (position != end) {
|
2005-11-10 21:42:42 +00:00
|
|
|
int newFacing2 = newFacing;
|
2005-11-01 14:19:50 +00:00
|
|
|
while (true) {
|
2005-11-10 21:42:42 +00:00
|
|
|
changePosTowardsFacing(xpos1, ypos1, facingTable1[start*8 + newFacing2]);
|
2005-11-01 14:19:50 +00:00
|
|
|
if (!lineIsPassable(xpos1, ypos1)) {
|
2005-11-10 21:42:42 +00:00
|
|
|
if (facingTable1[start*8 + newFacing2] == newFacing) {
|
2005-11-01 14:19:50 +00:00
|
|
|
return 0x7D00;
|
|
|
|
}
|
2005-11-10 21:42:42 +00:00
|
|
|
newFacing2 = facingTable1[start*8 + newFacing2];
|
2005-11-01 14:19:50 +00:00
|
|
|
xpos1 = x;
|
2005-11-10 21:42:42 +00:00
|
|
|
ypos1 = y;
|
2005-11-01 14:19:50 +00:00
|
|
|
continue;
|
|
|
|
}
|
2005-11-26 16:37:20 +00:00
|
|
|
newFacing = facingTable1[start*8 + newFacing2];
|
2005-11-01 14:19:50 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
// debug drawing
|
|
|
|
//if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
|
2005-11-26 16:37:20 +00:00
|
|
|
// _screen->setPagePixel(0, xpos1, ypos1, unkTable[start]);
|
2005-11-09 22:26:12 +00:00
|
|
|
// _screen->updateScreen();
|
|
|
|
// waitTicks(5);
|
|
|
|
//}
|
2005-11-01 14:19:50 +00:00
|
|
|
if (newFacing & 1) {
|
2005-11-26 16:37:20 +00:00
|
|
|
int temp = xpos1 + addPosTableX[newFacing + start * 8];
|
2005-11-01 14:19:50 +00:00
|
|
|
if (toX == temp) {
|
2005-11-26 16:37:20 +00:00
|
|
|
temp = ypos1 + addPosTableY[newFacing + start * 8];
|
2005-11-01 14:19:50 +00:00
|
|
|
if (toY == temp) {
|
|
|
|
moveTable[position++] = facingTable2[newFacing + start * 8];
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
moveTable[position++] = newFacing;
|
|
|
|
x = xpos1;
|
|
|
|
y = ypos1;
|
|
|
|
if (x == toX && y == toY) {
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos1 == xpos2 && ypos1 == ypos2) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-10 21:42:42 +00:00
|
|
|
newFacing = facingTable3[start*8 + newFacing];
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
return 0x7D00;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
|
|
|
|
debug(9, "getFacingFromPointToPoint(%d, %d, %d, %d)", x, y, toX, toY);
|
|
|
|
static const int facingTable[] = {
|
|
|
|
1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6
|
|
|
|
};
|
|
|
|
|
|
|
|
int facingEntry = 0;
|
|
|
|
int ydiff = y - toY;
|
|
|
|
if (ydiff < 0) {
|
|
|
|
++facingEntry;
|
|
|
|
ydiff = -ydiff;
|
|
|
|
}
|
|
|
|
facingEntry <<= 1;
|
|
|
|
|
|
|
|
int xdiff = toX - x;
|
|
|
|
if (xdiff < 0) {
|
|
|
|
++facingEntry;
|
|
|
|
xdiff = -xdiff;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xdiff >= ydiff) {
|
2005-11-13 19:35:01 +00:00
|
|
|
int temp = ydiff;
|
2005-11-01 14:19:50 +00:00
|
|
|
ydiff = xdiff;
|
|
|
|
xdiff = temp;
|
|
|
|
|
|
|
|
facingEntry <<= 1;
|
|
|
|
} else {
|
|
|
|
facingEntry <<= 1;
|
|
|
|
facingEntry += 1;
|
|
|
|
}
|
|
|
|
int temp = (ydiff + 1) >> 1;
|
|
|
|
|
|
|
|
if (xdiff < temp) {
|
|
|
|
facingEntry <<= 1;
|
|
|
|
facingEntry += 1;
|
|
|
|
} else {
|
|
|
|
facingEntry <<= 1;
|
|
|
|
}
|
|
|
|
assert(facingEntry < ARRAYSIZE(facingTable));
|
|
|
|
return facingTable[facingEntry];
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) {
|
|
|
|
debug(9, "changePosTowardsFacing(%d, %d, %d)", x, y, facing);
|
|
|
|
x += _addXPosTable[facing];
|
|
|
|
y += _addYPosTable[facing];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KyraEngine::lineIsPassable(int x, int y) {
|
|
|
|
debug(9, "lineIsPassable(%d, %d)", x, y);
|
|
|
|
if (queryGameFlag(0xEF)) {
|
|
|
|
if (_currentCharacter->sceneId == 5)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_pathfinderFlag & 2) {
|
|
|
|
if (x >= 312)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_pathfinderFlag & 4) {
|
|
|
|
if (y >= 136)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_pathfinderFlag & 8) {
|
|
|
|
if (x < 8)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_pathfinderFlag2) {
|
|
|
|
if (x <= 8 || x >= 312)
|
|
|
|
return true;
|
2005-11-10 21:42:42 +00:00
|
|
|
if (y < (_northExitHeight & 0xFF) || y > 135)
|
2005-11-01 14:19:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y > 137) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ypos = 8;
|
|
|
|
if (_scaleMode) {
|
2005-11-13 19:35:01 +00:00
|
|
|
ypos = (_scaleTable[y] >> 5) + 1;
|
|
|
|
if (8 < ypos)
|
|
|
|
ypos = 8;
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
x -= (ypos >> 1);
|
|
|
|
if (y < 0)
|
|
|
|
y = 0;
|
|
|
|
|
|
|
|
int xpos = x;
|
|
|
|
int xtemp = xpos + ypos - 1;
|
2005-11-13 19:35:01 +00:00
|
|
|
if (x < 0)
|
2005-11-01 14:19:50 +00:00
|
|
|
xpos = 0;
|
|
|
|
|
|
|
|
if (xtemp > 319)
|
|
|
|
xtemp = 319;
|
2005-11-10 21:42:42 +00:00
|
|
|
|
2005-11-01 14:19:50 +00:00
|
|
|
for (; xpos < xtemp; ++xpos) {
|
2005-11-10 21:42:42 +00:00
|
|
|
if (!_screen->getShapeFlag1(xpos, y))
|
2005-11-01 14:19:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::getMoveTableSize(int *moveTable) {
|
2005-11-18 23:55:31 +00:00
|
|
|
debug(9, "getMoveTableSize(0x%X)", moveTable);
|
2005-11-01 14:19:50 +00:00
|
|
|
int retValue = 0;
|
|
|
|
if (moveTable[0] == 8)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
static const int facingTable[] = {
|
|
|
|
4, 5, 6, 7, 0, 1, 2, 3
|
|
|
|
};
|
|
|
|
static const int unkTable[] = {
|
|
|
|
-1, -1, 1, 2, -1, 6, 7, -1,
|
|
|
|
-1, -1, -1, -1, 2, -1, 0, -1,
|
|
|
|
1, -1, -1, -1, 3, 4, -1, 0,
|
|
|
|
2, -1, -1, -1, -1, -1, 4, -1,
|
|
|
|
-1, 2, 3, -1, -1, -1, 5, 6,
|
|
|
|
6, -1, 4, -1, -1, -1, -1, -1,
|
|
|
|
7, 0, -1, 4, 5, -1, -1, -1,
|
|
|
|
-1, -1, 0, -1, 6, -1, -1, -1
|
|
|
|
};
|
|
|
|
|
|
|
|
int *oldPosition = moveTable;
|
|
|
|
int *tempPosition = moveTable;
|
2005-11-26 16:37:20 +00:00
|
|
|
int *curPosition = moveTable + 1;
|
|
|
|
retValue = 1;
|
2005-11-01 14:19:50 +00:00
|
|
|
|
|
|
|
while (*curPosition != 8) {
|
2005-11-18 23:55:31 +00:00
|
|
|
if (*oldPosition == facingTable[*curPosition]) {
|
2005-11-01 14:19:50 +00:00
|
|
|
retValue -= 2;
|
|
|
|
*oldPosition = 9;
|
|
|
|
*curPosition = 9;
|
|
|
|
|
|
|
|
while (tempPosition != moveTable) {
|
|
|
|
--tempPosition;
|
|
|
|
if (*tempPosition != 9)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tempPosition == moveTable && *tempPosition == 9) {
|
2005-11-18 23:55:31 +00:00
|
|
|
while (*tempPosition != 8 && *tempPosition == 9) {
|
2005-11-01 14:19:50 +00:00
|
|
|
++tempPosition;
|
|
|
|
}
|
|
|
|
if (*tempPosition == 8) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
oldPosition = tempPosition;
|
|
|
|
curPosition = oldPosition+1;
|
|
|
|
while (*curPosition != 8 && *curPosition == 9) {
|
2005-11-01 14:19:50 +00:00
|
|
|
++curPosition;
|
|
|
|
}
|
2005-11-18 23:55:31 +00:00
|
|
|
continue;
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
if (unkTable[*curPosition+((*oldPosition)*8)] != -1) {
|
2005-11-01 14:19:50 +00:00
|
|
|
--retValue;
|
2005-11-18 23:55:31 +00:00
|
|
|
*oldPosition = unkTable[*curPosition+((*oldPosition)*8)];
|
2005-11-01 14:19:50 +00:00
|
|
|
*curPosition = 9;
|
|
|
|
|
|
|
|
if (tempPosition != oldPosition) {
|
|
|
|
curPosition = oldPosition;
|
|
|
|
oldPosition = tempPosition;
|
2005-11-26 16:37:20 +00:00
|
|
|
while (true) {
|
|
|
|
if (tempPosition == moveTable) {
|
|
|
|
break;
|
|
|
|
}
|
2005-11-01 14:19:50 +00:00
|
|
|
--tempPosition;
|
2005-11-26 16:37:20 +00:00
|
|
|
if (*tempPosition != 9) {
|
|
|
|
break;
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2005-11-26 16:37:20 +00:00
|
|
|
while (true) {
|
2005-11-01 14:19:50 +00:00
|
|
|
++curPosition;
|
2005-11-26 16:37:20 +00:00
|
|
|
if (*curPosition != 9) {
|
|
|
|
break;
|
|
|
|
}
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
tempPosition = oldPosition;
|
|
|
|
oldPosition = curPosition;
|
|
|
|
++retValue;
|
2005-11-26 16:37:20 +00:00
|
|
|
while (true) {
|
2005-11-01 14:19:50 +00:00
|
|
|
++curPosition;
|
2005-11-26 16:37:20 +00:00
|
|
|
if (*curPosition != 9) {
|
|
|
|
break;
|
|
|
|
}
|
2005-11-01 14:19:50 +00:00
|
|
|
}
|
|
|
|
}
|
2005-11-26 16:37:20 +00:00
|
|
|
|
2005-11-01 14:19:50 +00:00
|
|
|
return retValue;
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Scene handling
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
|
|
|
|
debug(9, "handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset);
|
2005-11-13 19:35:01 +00:00
|
|
|
if (queryGameFlag(0xEF)) {
|
2005-11-09 22:26:12 +00:00
|
|
|
unk1 = 0;
|
|
|
|
}
|
|
|
|
int sceneId = _currentCharacter->sceneId;
|
|
|
|
_pathfinderFlag = 0;
|
|
|
|
if (xpos < 12) {
|
|
|
|
if (_roomTable[sceneId].westExit != 0xFFFF) {
|
|
|
|
xpos = 12;
|
|
|
|
ypos = _sceneExits.westYPos;
|
|
|
|
_pathfinderFlag = 7;
|
|
|
|
}
|
|
|
|
} else if(xpos >= 308) {
|
|
|
|
if (_roomTable[sceneId].eastExit != 0xFFFF) {
|
|
|
|
xpos = 307;
|
|
|
|
ypos = _sceneExits.eastYPos;
|
|
|
|
_pathfinderFlag = 13;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
if (ypos <= (_northExitHeight&0xFF)+2) {
|
2005-11-09 22:26:12 +00:00
|
|
|
if (_roomTable[sceneId].northExit != 0xFFFF) {
|
2005-11-13 19:35:01 +00:00
|
|
|
xpos = _sceneExits.northXPos;
|
|
|
|
ypos = _northExitHeight & 0xFF;
|
2005-11-09 22:26:12 +00:00
|
|
|
_pathfinderFlag = 14;
|
|
|
|
}
|
|
|
|
} else if (ypos >= 136) {
|
|
|
|
if (_roomTable[sceneId].southExit != 0xFFFF) {
|
2005-11-13 19:35:01 +00:00
|
|
|
xpos = _sceneExits.southXPos;
|
|
|
|
ypos = 136;
|
2005-11-09 22:26:12 +00:00
|
|
|
_pathfinderFlag = 11;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int temp = xpos - _currentCharacter->x1;
|
|
|
|
if (ABS(temp) < 4) {
|
|
|
|
temp = ypos - _currentCharacter->y1;
|
|
|
|
if (ABS(temp) < 2) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 23:02:16 +00:00
|
|
|
int x = (int16)(_currentCharacter->x1 & 0xFFFC);
|
|
|
|
int y = (int16)(_currentCharacter->y1 & 0xFFFE);
|
|
|
|
xpos = (int16)(xpos & 0xFFFC);
|
|
|
|
ypos = (int16)(ypos & 0xFFFE);
|
2005-11-09 22:26:12 +00:00
|
|
|
int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
|
|
|
|
_pathfinderFlag = 0;
|
|
|
|
if (ret >= _lastFindWayRet) {
|
|
|
|
_lastFindWayRet = ret;
|
|
|
|
}
|
|
|
|
if (ret == 0x7D00 || ret == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return processSceneChange(_movFacingTable, unk1, frameReset);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) {
|
2005-11-26 16:37:20 +00:00
|
|
|
debug(9, "processSceneChange(0x%X, %d, %d)", table, unk1, frameReset);
|
2005-11-09 22:26:12 +00:00
|
|
|
if (queryGameFlag(0xEF)) {
|
|
|
|
unk1 = 0;
|
|
|
|
}
|
|
|
|
int *tableStart = table;
|
|
|
|
_sceneChangeState = 0;
|
|
|
|
_loopFlag2 = 0;
|
|
|
|
bool running = true;
|
|
|
|
int returnValue = 0;
|
2005-11-26 16:37:20 +00:00
|
|
|
uint32 nextFrame = 0;
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag = false;
|
2005-12-24 18:00:35 +00:00
|
|
|
_mousePressFlag = false;
|
2005-11-09 22:26:12 +00:00
|
|
|
while (running) {
|
2005-12-13 15:10:20 +00:00
|
|
|
if (_abortWalkFlag) {
|
|
|
|
*table = 8;
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
processInput(_mouseX, _mouseY);
|
|
|
|
return 0;
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
bool forceContinue = false;
|
|
|
|
switch (*table) {
|
|
|
|
case 0: case 1: case 2:
|
|
|
|
case 3: case 4: case 5:
|
|
|
|
case 6: case 7:
|
|
|
|
_currentCharacter->facing = getOppositeFacingDirection(*table);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
forceContinue = true;
|
|
|
|
running = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++table;
|
|
|
|
forceContinue = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
returnValue = changeScene(_currentCharacter->facing);
|
2005-11-13 19:35:01 +00:00
|
|
|
if (returnValue) {
|
|
|
|
running = false;
|
2005-12-24 18:00:35 +00:00
|
|
|
_abortWalkFlag = false;
|
2005-11-13 19:35:01 +00:00
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
|
|
|
|
if (unk1) {
|
2005-12-24 18:00:35 +00:00
|
|
|
if (_mousePressFlag) {
|
|
|
|
running = false;
|
|
|
|
_sceneChangeState = 1;
|
|
|
|
}
|
2005-11-09 22:26:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (forceContinue || !running) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int temp = 0;
|
2005-11-26 16:37:20 +00:00
|
|
|
if (table == tableStart || table[1] == 8) {
|
2005-11-09 22:26:12 +00:00
|
|
|
temp = setCharacterPosition(0, 0);
|
|
|
|
} else {
|
|
|
|
temp = setCharacterPosition(0, table);
|
|
|
|
}
|
2005-11-26 16:37:20 +00:00
|
|
|
if (temp) {
|
|
|
|
++table;
|
2005-11-18 23:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nextFrame = getTimerDelay(5) * _tickLength + _system->getMillis();
|
|
|
|
while (_system->getMillis() < nextFrame) {
|
|
|
|
_sprites->updateSceneAnims();
|
|
|
|
updateMousePointer();
|
|
|
|
updateGameTimers();
|
|
|
|
updateAllObjectShapes();
|
2005-12-09 14:52:31 +00:00
|
|
|
updateTextFade();
|
2005-11-18 23:55:31 +00:00
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
// XXX updateKyragemFading
|
|
|
|
// XXX playEnd
|
|
|
|
// XXX
|
|
|
|
}
|
|
|
|
if ((nextFrame - _system->getMillis()) >= 10)
|
|
|
|
delay(10);
|
2005-11-09 22:26:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frameReset && !(_brandonStatusBit & 2)) {
|
|
|
|
_currentCharacter->currentAnimFrame = 7;
|
|
|
|
}
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::changeScene(int facing) {
|
2005-11-13 19:35:01 +00:00
|
|
|
debug(9, "changeScene(%d)", facing);
|
2005-11-09 22:26:12 +00:00
|
|
|
if (queryGameFlag(0xEF)) {
|
|
|
|
if (_currentCharacter->sceneId == 5) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int xpos = _charXPosTable[facing] + _currentCharacter->x1;
|
|
|
|
int ypos = _charYPosTable[facing] + _currentCharacter->y1;
|
|
|
|
|
|
|
|
if (xpos >= 12 && xpos <= 308) {
|
|
|
|
if (!lineIsPassable(xpos, ypos))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_exitListPtr) {
|
2005-11-13 19:35:01 +00:00
|
|
|
int16 *ptr = _exitListPtr;
|
2005-11-09 22:26:12 +00:00
|
|
|
// this loop should be only entered on time, seems to be some hack in the original
|
|
|
|
while (true) {
|
2005-11-13 19:35:01 +00:00
|
|
|
if (*ptr == -1)
|
2005-11-09 22:26:12 +00:00
|
|
|
break;
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
|
2005-11-09 22:26:12 +00:00
|
|
|
ptr += 10;
|
2005-11-10 21:42:42 +00:00
|
|
|
break;
|
2005-11-09 22:26:12 +00:00
|
|
|
}
|
2005-11-13 19:35:01 +00:00
|
|
|
_brandonPosX = ptr[6];
|
|
|
|
_brandonPosY = ptr[7];
|
|
|
|
uint16 sceneId = ptr[5];
|
|
|
|
facing = ptr[4];
|
|
|
|
int unk1 = ptr[8];
|
|
|
|
int unk2 = ptr[9];
|
2005-11-09 22:26:12 +00:00
|
|
|
if (sceneId == 0xFFFF) {
|
|
|
|
switch (facing) {
|
|
|
|
case 0:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].northExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].southExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].westExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_currentCharacter->facing = facing;
|
|
|
|
animRefreshNPC(0);
|
|
|
|
updateAllObjectShapes();
|
|
|
|
enterNewScene(sceneId, facing, unk1, unk2, 0);
|
2005-11-10 21:42:42 +00:00
|
|
|
resetGameFlag(0xEE);
|
2005-11-09 22:26:12 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int returnValue = 0;
|
|
|
|
facing = 0;
|
|
|
|
|
|
|
|
if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
|
|
|
|
facing = 0;
|
|
|
|
returnValue = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
|
|
|
|
facing = 2;
|
|
|
|
returnValue = 1;
|
|
|
|
}
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
|
2005-11-09 22:26:12 +00:00
|
|
|
facing = 4;
|
|
|
|
returnValue = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos <= 12 || _currentCharacter->y1 <= 12) {
|
|
|
|
facing = 6;
|
|
|
|
returnValue = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!returnValue)
|
|
|
|
return 0;
|
|
|
|
|
2005-11-13 19:35:01 +00:00
|
|
|
uint16 sceneId = 0xFFFF;
|
2005-11-09 22:26:12 +00:00
|
|
|
switch (facing) {
|
|
|
|
case 0:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].northExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].southExit;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
sceneId = _roomTable[_currentCharacter->sceneId].westExit;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sceneId == 0xFFFF)
|
|
|
|
return 0;
|
2005-11-13 19:35:01 +00:00
|
|
|
|
2005-11-09 22:26:12 +00:00
|
|
|
enterNewScene(sceneId, facing, 1, 1, 0);
|
|
|
|
return returnValue;
|
|
|
|
}
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Timer handling
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
void KyraEngine::setupTimers() {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "setupTimers()");
|
2005-11-11 22:17:06 +00:00
|
|
|
memset(_timers, 0, sizeof(_timers));
|
|
|
|
|
|
|
|
for (int i = 0; i < 34; i++)
|
|
|
|
_timers[i].active = 1;
|
|
|
|
|
|
|
|
_timers[0].func = _timers[1].func = _timers[2].func = _timers[3].func = _timers[4].func = 0; //Unused.
|
|
|
|
_timers[5].func = _timers[6].func = _timers[7].func = _timers[8].func = _timers[9].func = 0; //_nullsub51;
|
|
|
|
_timers[10].func = _timers[11].func = _timers[12].func = _timers[13].func = 0; //_nullsub50;
|
2005-12-09 14:52:31 +00:00
|
|
|
_timers[14].func = &KyraEngine::timerCheckAnimFlag2; //_nullsub52;
|
2005-11-11 22:17:06 +00:00
|
|
|
_timers[15].func = &KyraEngine::timerUpdateHeadAnims; //_nullsub48;
|
|
|
|
_timers[16].func = &KyraEngine::timerSetFlags1; //_nullsub47;
|
|
|
|
_timers[17].func = 0; //sub_15120;
|
|
|
|
_timers[18].func = &KyraEngine::timerCheckAnimFlag1; //_nullsub53;
|
|
|
|
_timers[19].func = &KyraEngine::timerRedrawAmulet; //_nullsub54;
|
|
|
|
_timers[20].func = 0; //offset _timerDummy1
|
|
|
|
_timers[21].func = 0; //sub_1517C;
|
|
|
|
_timers[22].func = 0; //offset _timerDummy2
|
|
|
|
_timers[23].func = 0; //offset _timerDummy3,
|
|
|
|
_timers[24].func = 0; //_nullsub45;
|
|
|
|
_timers[25].func = 0; //offset _timerDummy4
|
|
|
|
_timers[26].func = 0; //_nullsub46;
|
|
|
|
_timers[27].func = 0; //offset _timerDummy5,
|
|
|
|
_timers[28].func = 0; //offset _timerDummy6
|
|
|
|
_timers[29].func = 0; //offset _timerDummy7,
|
|
|
|
_timers[30].func = 0; //offset _timerDummy8,
|
2005-12-09 14:52:31 +00:00
|
|
|
_timers[31].func = &KyraEngine::timerFadeText; //sub_151F8;
|
2005-12-29 22:18:40 +00:00
|
|
|
_timers[32].func = &KyraEngine::updateAnimFlag1; //_nullsub61;
|
|
|
|
_timers[33].func = &KyraEngine::updateAnimFlag2; //_nullsub62;
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
_timers[0].countdown = _timers[1].countdown = _timers[2].countdown = _timers[3].countdown = _timers[4].countdown = -1;
|
|
|
|
_timers[5].countdown = 5;
|
|
|
|
_timers[6].countdown = 7;
|
|
|
|
_timers[7].countdown = 8;
|
|
|
|
_timers[8].countdown = 9;
|
|
|
|
_timers[9].countdown = 7;
|
|
|
|
_timers[10].countdown = _timers[11].countdown = _timers[12].countdown = _timers[13].countdown = 420;
|
|
|
|
_timers[14].countdown = 600;
|
|
|
|
_timers[15].countdown = 11;
|
|
|
|
_timers[16].countdown = _timers[17].countdown = 7200;
|
|
|
|
_timers[18].countdown = _timers[19].countdown = 600;
|
|
|
|
_timers[20].countdown = 7200;
|
|
|
|
_timers[21].countdown = 18000;
|
|
|
|
_timers[22].countdown = 7200;
|
|
|
|
_timers[23].countdown = _timers[24].countdown = _timers[25].countdown = _timers[26].countdown = _timers[27].countdown = 10800;
|
|
|
|
_timers[28].countdown = 21600;
|
|
|
|
_timers[29].countdown = 7200;
|
|
|
|
_timers[30].countdown = 10800;
|
|
|
|
_timers[31].countdown = -1;
|
|
|
|
_timers[32].countdown = 9;
|
|
|
|
_timers[33].countdown = 3;
|
2005-11-18 23:55:31 +00:00
|
|
|
}
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
void KyraEngine::updateGameTimers() {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "updateGameTimers()");
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
if (_system->getMillis() < _timerNextRun)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_timerNextRun += 99999;
|
|
|
|
|
|
|
|
for (int i = 0; i < 34; i++) {
|
|
|
|
if (_timers[i].active && _timers[i].countdown > -1) {
|
|
|
|
if (_timers[i].nextRun <=_system->getMillis()) {
|
2005-12-09 14:52:31 +00:00
|
|
|
if (i > 4 && _timers[i].func)
|
|
|
|
(*this.*_timers[i].func)(i);
|
2005-11-11 22:17:06 +00:00
|
|
|
|
|
|
|
_timers[i].nextRun = _system->getMillis() + _timers[i].countdown * _tickLength;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (_timers[i].nextRun < _timerNextRun)
|
|
|
|
_timerNextRun = _timers[i].nextRun;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::clearNextEventTickCount() {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "clearNextEventTickCount()");
|
2005-11-11 22:17:06 +00:00
|
|
|
_timerNextRun = 0;
|
|
|
|
}
|
|
|
|
|
2005-12-09 23:48:52 +00:00
|
|
|
void KyraEngine::setTimerDelay(uint8 timer, int32 countdown) {
|
|
|
|
debug(9, "setTimerDelay(%i, %d)", timer, countdown);
|
|
|
|
_timers[timer].countdown = countdown;
|
|
|
|
}
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
int16 KyraEngine::getTimerDelay(uint8 timer) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "getTimerDelay(%i)", timer);
|
2005-11-11 22:17:06 +00:00
|
|
|
return _timers[timer].countdown;
|
|
|
|
}
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
void KyraEngine::setTimerCountdown(uint8 timer, int32 countdown) {
|
|
|
|
debug(9, "setTimerCountdown(%i, %i)", timer, countdown);
|
2005-11-11 22:17:06 +00:00
|
|
|
_timers[timer].countdown = countdown;
|
|
|
|
|
|
|
|
uint32 nextRun = _system->getMillis() + countdown;
|
|
|
|
if (nextRun < _timerNextRun)
|
|
|
|
_timerNextRun = nextRun;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::enableTimer(uint8 timer) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "enableTimer(%i)", timer);
|
2005-11-11 22:17:06 +00:00
|
|
|
_timers[timer].active = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::disableTimer(uint8 timer) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "disableTimer(%i)", timer);
|
2005-11-11 22:17:06 +00:00
|
|
|
_timers[timer].active = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::timerUpdateHeadAnims(int timerNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "timerUpdateHeadAnims(%i)", timerNum);
|
2005-11-11 22:17:06 +00:00
|
|
|
static int8 currentFrame = 0;
|
|
|
|
static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5,
|
|
|
|
4, 4, 6, 4, 8, 1, 9, 4, -1};
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
if (_talkingCharNum < 0)
|
2005-11-11 22:17:06 +00:00
|
|
|
return;
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
_currHeadShape = frameTable[currentFrame];
|
2005-11-11 22:17:06 +00:00
|
|
|
currentFrame++;
|
|
|
|
|
|
|
|
if (frameTable[currentFrame] == -1)
|
|
|
|
currentFrame = 0;
|
|
|
|
|
|
|
|
animRefreshNPC(0);
|
2005-12-09 14:52:31 +00:00
|
|
|
animRefreshNPC(_talkingCharNum);
|
2005-11-11 22:17:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::timerSetFlags1(int timerNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "timerSetFlags(%i)", timerNum);
|
2005-11-11 22:17:06 +00:00
|
|
|
if (_currentCharacter->sceneId == 0x1C)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int rndNr = _rnd.getRandomNumberRng(0, 3);
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
if (!queryGameFlag(rndNr + 17)) {
|
|
|
|
setGameFlag(rndNr + 17);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
rndNr++;
|
|
|
|
if (rndNr > 3)
|
|
|
|
rndNr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
void KyraEngine::timerFadeText(int timerNum) {
|
|
|
|
debug(9, "timerFadeText(%i)", timerNum);
|
|
|
|
_fadeText = true;
|
|
|
|
}
|
|
|
|
|
2005-12-29 22:18:40 +00:00
|
|
|
void KyraEngine::updateAnimFlag1(int timerNum) {
|
|
|
|
debug(9, "updateAnimFlag1(%d)", timerNum);
|
|
|
|
if (_brandonStatusBit & 2) {
|
|
|
|
_brandonStatusBit0x02Flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::updateAnimFlag2(int timerNum) {
|
|
|
|
debug(9, "updateAnimFlag2(%d)", timerNum);
|
|
|
|
if (_brandonStatusBit & 0x20) {
|
|
|
|
_brandonStatusBit0x20Flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
void KyraEngine::setTextFadeTimerCountdown(int16 countdown) {
|
|
|
|
debug(9, "setTextFadeTimerCountdown(%i)", countdown);
|
|
|
|
//if (countdown == -1)
|
|
|
|
//countdown = 32000;
|
|
|
|
|
|
|
|
setTimerCountdown(31, countdown*60);
|
|
|
|
}
|
|
|
|
|
2005-11-11 22:17:06 +00:00
|
|
|
void KyraEngine::timerSetFlags2(int timerNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "timerSetFlags2(%i)", timerNum);
|
2005-11-11 22:17:06 +00:00
|
|
|
if (!((uint32*)(_flagsTable+0x2D))[timerNum])
|
|
|
|
((uint32*)(_flagsTable+0x2D))[timerNum] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::timerCheckAnimFlag1(int timerNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "timerCheckAnimFlag1(%i)", timerNum);
|
2005-11-11 22:17:06 +00:00
|
|
|
if (_brandonStatusBit & 0x20) {
|
2005-12-09 14:52:31 +00:00
|
|
|
checkAmuletAnimFlags();
|
2005-11-11 22:17:06 +00:00
|
|
|
setTimerCountdown(18, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::timerCheckAnimFlag2(int timerNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "timerCheckAnimFlag1(%i)", timerNum);
|
2005-11-11 22:17:06 +00:00
|
|
|
if (_brandonStatusBit & 0x2) {
|
2005-12-09 14:52:31 +00:00
|
|
|
checkAmuletAnimFlags();
|
2005-11-11 22:17:06 +00:00
|
|
|
setTimerCountdown(14, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 14:52:31 +00:00
|
|
|
void KyraEngine::checkAmuletAnimFlags() {
|
|
|
|
debug(9, "checkSpecialAnimFlags()");
|
2005-11-11 22:17:06 +00:00
|
|
|
if (_brandonStatusBit & 2) {
|
2005-12-29 22:18:40 +00:00
|
|
|
seq_makeBrandonNormal2();
|
2005-11-11 22:17:06 +00:00
|
|
|
setTimerCountdown(19, 300);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_brandonStatusBit & 0x20) {
|
2005-12-29 22:18:40 +00:00
|
|
|
seq_makeBrandonNormal();
|
2005-11-11 22:17:06 +00:00
|
|
|
setTimerCountdown(19, 300);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::timerRedrawAmulet(int timerNum) {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "timerRedrawAmulet(%i)", timerNum);
|
2005-12-26 14:53:51 +00:00
|
|
|
if (queryGameFlag(0xF1)) {
|
2005-11-11 22:17:06 +00:00
|
|
|
drawAmulet();
|
2005-12-09 14:52:31 +00:00
|
|
|
setTimerCountdown(19, -1);
|
2005-11-11 22:17:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::drawAmulet() {
|
2005-12-09 14:52:31 +00:00
|
|
|
debug(9, "drawAmulet()");
|
2005-11-11 22:17:06 +00:00
|
|
|
static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1};
|
|
|
|
static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1};
|
|
|
|
static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1};
|
|
|
|
static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1};
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
resetGameFlag(0xF1);
|
2005-11-11 22:17:06 +00:00
|
|
|
_screen->hideMouse();
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
while (amuletTable1[i] != -1) {
|
|
|
|
if (queryGameFlag(87))
|
|
|
|
_screen->drawShape(0, _shapes[4+amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0);
|
|
|
|
|
|
|
|
if (queryGameFlag(89))
|
|
|
|
_screen->drawShape(0, _shapes[4+amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0);
|
|
|
|
|
|
|
|
if (queryGameFlag(86))
|
|
|
|
_screen->drawShape(0, _shapes[4+amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0);
|
|
|
|
|
|
|
|
if (queryGameFlag(88))
|
|
|
|
_screen->drawShape(0, _shapes[4+amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0);
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
_screen->updateScreen();
|
|
|
|
delayWithTicks(3);
|
2005-11-11 22:17:06 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Input
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
void KyraEngine::processInput(int xpos, int ypos) {
|
|
|
|
debug(9, "processInput(%d, %d)", xpos, ypos);
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = false;
|
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
if (processInputHelper(xpos, ypos)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
uint8 item = findItemAtPos(xpos, ypos);
|
|
|
|
if (item == 0xFF) {
|
2005-12-24 18:00:35 +00:00
|
|
|
_changedScene = false;
|
2005-12-26 17:31:42 +00:00
|
|
|
int handled = clickEventHandler(xpos, ypos);
|
|
|
|
if (_changedScene || handled)
|
2005-11-18 23:55:31 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX _deathHandler specific
|
|
|
|
if (ypos <= 158) {
|
|
|
|
uint16 exit = 0xFFFF;
|
|
|
|
if (xpos < 12) {
|
|
|
|
exit = _walkBlockWest;
|
|
|
|
} else if (xpos >= 308) {
|
|
|
|
exit = _walkBlockEast;
|
|
|
|
} else if (ypos >= 136) {
|
|
|
|
exit = _walkBlockSouth;
|
|
|
|
} else if (ypos < 12) {
|
|
|
|
exit = _walkBlockNorth;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exit != 0xFFFF) {
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = true;
|
2005-11-18 23:55:31 +00:00
|
|
|
handleSceneChange(xpos, ypos, 1, 1);
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = false;
|
2005-11-18 23:55:31 +00:00
|
|
|
return;
|
2005-12-09 19:49:47 +00:00
|
|
|
} else {
|
2005-12-09 23:02:16 +00:00
|
|
|
int script = checkForNPCScriptRun(xpos, ypos);
|
|
|
|
if (script >= 0) {
|
|
|
|
runNpcScript(script);
|
|
|
|
return;
|
|
|
|
}
|
2005-12-09 19:49:47 +00:00
|
|
|
if (_itemInHand != -1) {
|
|
|
|
if (ypos < 155) {
|
|
|
|
if (hasClickedOnExit(xpos, ypos)) {
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = true;
|
2005-12-09 19:49:47 +00:00
|
|
|
handleSceneChange(xpos, ypos, 1, 1);
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = false;
|
2005-12-09 19:49:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
dropItem(0, _itemInHand, xpos, ypos, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (ypos <= 155) {
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = true;
|
2005-12-09 19:49:47 +00:00
|
|
|
handleSceneChange(xpos, ypos, 1, 1);
|
2005-12-13 15:10:20 +00:00
|
|
|
_abortWalkFlag2 = false;
|
2005-12-09 19:49:47 +00:00
|
|
|
}
|
|
|
|
}
|
2005-11-18 23:55:31 +00:00
|
|
|
}
|
2005-12-09 17:36:57 +00:00
|
|
|
}
|
2005-11-18 23:55:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::processInputHelper(int xpos, int ypos) {
|
|
|
|
debug(9, "processInputHelper(%d, %d)", xpos, ypos);
|
2005-12-09 17:36:57 +00:00
|
|
|
uint8 item = findItemAtPos(xpos, ypos);
|
|
|
|
if (item != 0xFF) {
|
|
|
|
if (_itemInHand == -1) {
|
|
|
|
_screen->hideMouse();
|
|
|
|
animRemoveGameItem(item);
|
|
|
|
// XXX call kyraPlaySound(53)
|
|
|
|
assert(_currentCharacter->sceneId < _roomTableSize);
|
|
|
|
Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
|
|
|
|
int item2 = currentRoom->itemsTable[item];
|
|
|
|
currentRoom->itemsTable[item] = 0xFF;
|
|
|
|
setMouseItem(item2);
|
2005-12-14 14:08:30 +00:00
|
|
|
assert(_itemList && _takenList);
|
|
|
|
updateSentenceCommand(_itemList[item2], _takenList[0], 179);
|
2005-12-09 17:36:57 +00:00
|
|
|
_itemInHand = item2;
|
|
|
|
_screen->showMouse();
|
|
|
|
clickEventHandler2();
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
exchangeItemWithMouseItem(_currentCharacter->sceneId, item);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2005-11-18 23:55:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::clickEventHandler(int xpos, int ypos) {
|
|
|
|
debug(9, "clickEventHandler(%d, %d)", xpos, ypos);
|
|
|
|
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
|
|
|
|
_scriptClick->variables[1] = xpos;
|
|
|
|
_scriptClick->variables[2] = ypos;
|
|
|
|
_scriptClick->variables[3] = 0;
|
|
|
|
_scriptClick->variables[4] = _itemInHand;
|
|
|
|
_scriptInterpreter->startScript(_scriptClick, 1);
|
2005-12-24 18:00:35 +00:00
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
while (_scriptInterpreter->validScript(_scriptClick)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
}
|
2005-12-24 18:00:35 +00:00
|
|
|
|
2005-11-18 23:55:31 +00:00
|
|
|
return _scriptClick->variables[3];
|
|
|
|
}
|
|
|
|
|
2005-12-13 15:10:20 +00:00
|
|
|
void KyraEngine::updateMousePointer(bool forceUpdate) {
|
2005-11-18 23:55:31 +00:00
|
|
|
int shape = 0;
|
|
|
|
|
|
|
|
int newMouseState = 0;
|
2005-12-08 17:19:18 +00:00
|
|
|
int newX = 0;
|
|
|
|
int newY = 0;
|
2005-11-18 23:55:31 +00:00
|
|
|
if (_mouseY <= 158) {
|
|
|
|
if (_mouseX >= 12) {
|
|
|
|
if (_mouseX >= 308) {
|
|
|
|
if (_walkBlockEast == 0xFFFF) {
|
|
|
|
newMouseState = -2;
|
|
|
|
} else {
|
|
|
|
newMouseState = -5;
|
|
|
|
shape = 3;
|
|
|
|
newX = 7;
|
|
|
|
newY = 5;
|
|
|
|
}
|
|
|
|
} else if (_mouseY >= 136) {
|
|
|
|
if (_walkBlockSouth == 0xFFFF) {
|
|
|
|
newMouseState = -2;
|
|
|
|
} else {
|
|
|
|
newMouseState = -4;
|
|
|
|
shape = 4;
|
|
|
|
newX = 5;
|
|
|
|
newY = 7;
|
|
|
|
}
|
|
|
|
} else if (_mouseY < 12) {
|
|
|
|
if (_walkBlockNorth == 0xFFFF) {
|
|
|
|
newMouseState = -2;
|
|
|
|
} else {
|
|
|
|
newMouseState = -6;
|
|
|
|
shape = 2;
|
|
|
|
newX = 5;
|
|
|
|
newY = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_walkBlockWest == 0xFFFF) {
|
|
|
|
newMouseState = -2;
|
|
|
|
} else {
|
|
|
|
newMouseState = -3;
|
|
|
|
newX = 1;
|
|
|
|
newY = shape = 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_mouseX >= _entranceMouseCursorTracks[0] && _mouseY >= _entranceMouseCursorTracks[1]
|
|
|
|
&& _mouseX <= _entranceMouseCursorTracks[2] && _mouseY <= _entranceMouseCursorTracks[3]) {
|
|
|
|
switch (_entranceMouseCursorTracks[4]) {
|
|
|
|
case 0:
|
|
|
|
newMouseState = -6;
|
|
|
|
shape = 2;
|
|
|
|
newX = 5;
|
|
|
|
newY = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
newMouseState = -5;
|
|
|
|
shape = 3;
|
|
|
|
newX = 7;
|
|
|
|
newY = 5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
newMouseState = -4;
|
|
|
|
shape = 4;
|
|
|
|
newX = 5;
|
|
|
|
newY = 7;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
newMouseState = -3;
|
|
|
|
shape = 5;
|
|
|
|
newX = 1;
|
|
|
|
newY = 5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newMouseState == -2) {
|
|
|
|
shape = 6;
|
|
|
|
newX = 4;
|
|
|
|
newY = 4;
|
|
|
|
}
|
|
|
|
|
2005-12-13 15:10:20 +00:00
|
|
|
if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) {
|
2005-11-18 23:55:31 +00:00
|
|
|
_mouseState = newMouseState;
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->setMouseCursor(newX, newY, _shapes[4+shape]);
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!newMouseState) {
|
2005-12-13 15:10:20 +00:00
|
|
|
if (_mouseState != _itemInHand || forceUpdate) {
|
|
|
|
if (_mouseY > 158 || (_mouseX >= 12 && _mouseX < 308 && _mouseY < 136 && _mouseY >= 12) || forceUpdate) {
|
2005-11-18 23:55:31 +00:00
|
|
|
_mouseState = _itemInHand;
|
|
|
|
_screen->hideMouse();
|
|
|
|
if (_itemInHand == -1) {
|
|
|
|
_screen->setMouseCursor(1, 1, _shapes[4]);
|
|
|
|
} else {
|
|
|
|
_screen->setMouseCursor(8, 15, _shapes[220+_itemInHand]);
|
|
|
|
}
|
|
|
|
_screen->showMouse();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 19:49:47 +00:00
|
|
|
bool KyraEngine::hasClickedOnExit(int xpos, int ypos) {
|
|
|
|
debug(9, "hasClickedOnExit(%d, %d)", xpos, ypos);
|
|
|
|
if (xpos < 16 || xpos >= 304) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (ypos < 8)
|
|
|
|
return true;
|
|
|
|
if (ypos < 136 || ypos > 155) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-12-08 17:19:18 +00:00
|
|
|
void KyraEngine::clickEventHandler2() {
|
|
|
|
debug(9, "clickEventHandler2()");
|
|
|
|
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
|
|
|
|
_scriptClick->variables[0] = _currentCharacter->sceneId;
|
|
|
|
_scriptClick->variables[1] = _mouseX;
|
|
|
|
_scriptClick->variables[2] = _mouseY;
|
|
|
|
_scriptClick->variables[4] = _itemInHand;
|
|
|
|
_scriptInterpreter->startScript(_scriptClick, 6);
|
|
|
|
|
|
|
|
while (_scriptInterpreter->validScript(_scriptClick)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 23:02:16 +00:00
|
|
|
int KyraEngine::checkForNPCScriptRun(int xpos, int ypos) {
|
|
|
|
debug(9, "checkForNPCScriptRun(%d, %d)", xpos, ypos);
|
|
|
|
int returnValue = -1;
|
|
|
|
const Character *currentChar = _currentCharacter;
|
|
|
|
int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0;
|
|
|
|
|
|
|
|
int scaleFactor = _scaleTable[currentChar->y1];
|
|
|
|
int addX = (((scaleFactor*8)*3)>>8)>>1;
|
|
|
|
int addY = ((scaleFactor*3)<<4)>>8;
|
|
|
|
|
|
|
|
charLeft = currentChar->x1 - addX;
|
|
|
|
charRight = currentChar->x1 + addX;
|
|
|
|
charTop = currentChar->y1 - addY;
|
|
|
|
charBottom = currentChar->y1;
|
|
|
|
|
|
|
|
if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xpos > 304 || xpos < 16) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < 5; ++i) {
|
|
|
|
currentChar = &_characterList[i];
|
|
|
|
|
|
|
|
if (currentChar->sceneId != _currentCharacter->sceneId)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
charLeft = currentChar->x1 - 12;
|
|
|
|
charRight = currentChar->x1 + 11;
|
|
|
|
charTop = currentChar->y1 - 48;
|
|
|
|
// if (!i) {
|
|
|
|
// charBottom = currentChar->y2 - 16;
|
|
|
|
// } else {
|
|
|
|
charBottom = currentChar->y1;
|
|
|
|
// }
|
|
|
|
|
|
|
|
if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (returnValue != -1) {
|
|
|
|
if (currentChar->y1 >= _characterList[returnValue].y1) {
|
|
|
|
returnValue = i;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
returnValue = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::runNpcScript(int func) {
|
|
|
|
debug(9, "runNpcScript(%d)", func);
|
|
|
|
_scriptInterpreter->initScript(_npcScript, _npcScriptData);
|
|
|
|
_scriptInterpreter->startScript(_npcScript, func);
|
|
|
|
_npcScript->variables[0] = _currentCharacter->sceneId;
|
|
|
|
_npcScript->variables[4] = _itemInHand;
|
|
|
|
_npcScript->variables[5] = func;
|
|
|
|
|
|
|
|
while (_scriptInterpreter->validScript(_npcScript)) {
|
|
|
|
_scriptInterpreter->runScript(_npcScript);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-10 17:51:40 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Saving/loading
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
void KyraEngine::loadGame(const char *fileName) {
|
|
|
|
debug(9, "loadGame('%s')", fileName);
|
|
|
|
Common::InSaveFile *in;
|
|
|
|
|
|
|
|
if (!(in = _saveFileMan->openForLoading(fileName))) {
|
|
|
|
warning("Can't open file '%s', game not loaded", fileName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in->readByte() != 1) {
|
|
|
|
warning("Savegame is not the right version");
|
|
|
|
delete in;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char saveName[31];
|
|
|
|
in->read(saveName, 31);
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; i++) {
|
|
|
|
_characterList[i].sceneId = in->readUint16BE();
|
|
|
|
_characterList[i].height = in->readByte();
|
|
|
|
_characterList[i].facing = in->readByte();
|
|
|
|
_characterList[i].currentAnimFrame = in->readUint16BE();
|
|
|
|
_characterList[i].unk6 = in->readUint32BE();
|
|
|
|
in->read(_characterList[i].inventoryItems, 10);
|
|
|
|
_characterList[i].x1 = in->readSint16BE();
|
|
|
|
_characterList[i].y1 = in->readSint16BE();
|
|
|
|
_characterList[i].x2 = in->readSint16BE();
|
|
|
|
_characterList[i].y1 = in->readSint16BE();
|
|
|
|
_characterList[i].field_20 = in->readUint16BE();
|
|
|
|
_characterList[i].field_23 = in->readUint16BE();
|
|
|
|
}
|
|
|
|
|
|
|
|
_marbleVaseItem = in->readSint16BE();
|
|
|
|
_itemInHand = in->readByte();
|
|
|
|
|
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
_timers[i].countdown = in->readSint32BE();
|
|
|
|
_timers[i].nextRun = in->readUint32BE();
|
|
|
|
}
|
|
|
|
_timerNextRun = 0;
|
|
|
|
|
|
|
|
in->read(_flagsTable, sizeof(_flagsTable));
|
|
|
|
|
|
|
|
for (int i = 0; i < _roomTableSize; ++i) {
|
|
|
|
for (int item = 0; item < 12; ++item) {
|
|
|
|
_roomTable[i].itemsTable[item] = 0xFF;
|
|
|
|
_roomTable[i].itemsXPos[item] = 0xFFFF;
|
|
|
|
_roomTable[i].itemsYPos[item] = 0xFF;
|
|
|
|
_roomTable[i].unkField3[item] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 sceneId;
|
|
|
|
uint8 itemCount;
|
|
|
|
|
|
|
|
while (!in->eos()) {
|
|
|
|
sceneId = in->readUint16BE();
|
|
|
|
if (sceneId == 0xffff)
|
|
|
|
break;
|
|
|
|
|
|
|
|
itemCount = in->readByte();
|
|
|
|
for (int i = 0; i < itemCount; i++) {
|
|
|
|
_roomTable[sceneId].itemsTable[i] = in->readByte();
|
|
|
|
_roomTable[sceneId].itemsXPos[i] = in->readUint16BE();
|
|
|
|
_roomTable[sceneId].itemsYPos[i] = in->readUint16BE();
|
|
|
|
_roomTable[sceneId].unkField3[i] = in->readUint32BE();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
createMouseItem(_itemInHand);
|
|
|
|
enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1);
|
|
|
|
|
|
|
|
if (in->ioFailed())
|
|
|
|
error("Load failed.");
|
|
|
|
else
|
|
|
|
debug(1, "Loaded savegame '%s.'", saveName);
|
|
|
|
|
|
|
|
delete in;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::saveGame(const char *fileName, const char *saveName) {
|
|
|
|
debug(9, "saveGame('%s', '%s')", fileName, saveName);
|
|
|
|
Common::OutSaveFile *out;
|
|
|
|
|
|
|
|
if (!(out = _saveFileMan->openForSaving(fileName))) {
|
|
|
|
warning("Can't create file '%s', game not saved", fileName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Savegame version
|
|
|
|
out->writeByte(1);
|
|
|
|
out->write(saveName, 31);
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; i++) {
|
|
|
|
out->writeUint16BE(_characterList[i].sceneId);
|
|
|
|
out->writeByte(_characterList[i].height);
|
|
|
|
out->writeByte(_characterList[i].facing);
|
|
|
|
out->writeUint16BE(_characterList[i].currentAnimFrame);
|
|
|
|
out->writeUint32BE(_characterList[i].unk6);
|
|
|
|
out->write(_characterList[i].inventoryItems, 10);
|
|
|
|
out->writeSint16BE(_characterList[i].x1);
|
|
|
|
out->writeSint16BE(_characterList[i].y1);
|
|
|
|
out->writeSint16BE(_characterList[i].x2);
|
|
|
|
out->writeSint16BE(_characterList[i].y1);
|
|
|
|
out->writeUint16BE(_characterList[i].field_20);
|
|
|
|
out->writeUint16BE(_characterList[i].field_23);
|
|
|
|
}
|
|
|
|
|
|
|
|
out->writeSint16BE(_marbleVaseItem);
|
|
|
|
out->writeByte(_itemInHand);
|
|
|
|
|
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
out->writeSint32BE(_timers[i].countdown);
|
|
|
|
out->writeUint32BE(_timers[i].nextRun);
|
|
|
|
}
|
|
|
|
|
|
|
|
out->write(_flagsTable, sizeof(_flagsTable));
|
|
|
|
|
|
|
|
uint8 itemCount;
|
|
|
|
for (int i = 0; i < _roomTableSize; i++) {
|
|
|
|
itemCount = countItemsInScene(i);
|
|
|
|
if (itemCount > 0) {
|
|
|
|
out->writeUint16BE(i);
|
|
|
|
out->writeByte(itemCount);
|
|
|
|
for (int a = 0; a < 12; a++) {
|
|
|
|
if (_roomTable[i].itemsTable[a] != 0xff) {
|
|
|
|
out->writeByte(_roomTable[i].itemsTable[a]);
|
|
|
|
out->writeUint16BE(_roomTable[i].itemsXPos[a]);
|
|
|
|
out->writeUint16BE(_roomTable[i].itemsYPos[a]);
|
|
|
|
out->writeUint32BE(_roomTable[i].unkField3[a]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out->flush();
|
|
|
|
|
|
|
|
// check for errors
|
|
|
|
if (out->ioFailed())
|
|
|
|
warning("Can't write file '%s'. (Disk full?)", fileName);
|
|
|
|
else
|
|
|
|
debug(1, "Saved game '%s.'", saveName);
|
|
|
|
|
|
|
|
delete out;
|
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark - Button handling
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
Button *KyraEngine::initButton(Button *list, Button *newButton) {
|
|
|
|
if (!newButton)
|
|
|
|
return list;
|
|
|
|
if (!list)
|
|
|
|
return newButton;
|
|
|
|
Button *cur = list;
|
|
|
|
while (true) {
|
|
|
|
if (!cur->nextButton) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cur = cur->nextButton;
|
|
|
|
}
|
|
|
|
cur->nextButton = newButton;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine::buttonInventoryCallback(Button *caller) {
|
|
|
|
int itemOffset = caller->specialValue - 2;
|
|
|
|
uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset];
|
|
|
|
if (_itemInHand == -1) {
|
|
|
|
if (inventoryItem == 0xFF) {
|
|
|
|
// snd_playSoundEffect(0x36);
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12);
|
|
|
|
// snd_playSoundEffect(0x35);
|
|
|
|
setMouseItem(inventoryItem);
|
|
|
|
updateSentenceCommand(_itemList[inventoryItem], _takenList[0], 179);
|
|
|
|
_itemInHand = inventoryItem;
|
|
|
|
_screen->showMouse();
|
|
|
|
_currentCharacter->inventoryItems[itemOffset] = 0xFF;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (inventoryItem != 0xFF) {
|
|
|
|
// snd_playSoundEffect(0x35);
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12);
|
|
|
|
_screen->drawShape(0, _shapes[220+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0);
|
|
|
|
setMouseItem(inventoryItem);
|
|
|
|
updateSentenceCommand(_itemList[inventoryItem], _takenList[1], 179);
|
|
|
|
_screen->showMouse();
|
|
|
|
_currentCharacter->inventoryItems[itemOffset] = _itemInHand;
|
|
|
|
_itemInHand = inventoryItem;
|
|
|
|
} else {
|
|
|
|
// snd_playSoundEffect(0x32);
|
|
|
|
_screen->hideMouse();
|
|
|
|
_screen->drawShape(0, _shapes[220+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0);
|
|
|
|
_screen->setMouseCursor(1, 1, _shapes[4]);
|
|
|
|
updateSentenceCommand(_itemList[_itemInHand], _placedList[0], 179);
|
|
|
|
_screen->showMouse();
|
|
|
|
_currentCharacter->inventoryItems[itemOffset] = _itemInHand;
|
|
|
|
_itemInHand = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_screen->updateScreen();
|
|
|
|
// XXX clearKyrandiaButtonIO
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-12-26 14:53:51 +00:00
|
|
|
int KyraEngine::buttonAmuletCallback(Button *caller) {
|
|
|
|
if (!(_deathHandler & 8))
|
|
|
|
return 1;
|
|
|
|
int jewel = caller->specialValue - 0x14;
|
|
|
|
if (_currentCharacter->sceneId == 210) {
|
|
|
|
//if (_unkSceneVar == 4 || _unkSceneVar == 6)
|
|
|
|
// return 1;
|
|
|
|
}
|
|
|
|
if (!queryGameFlag(0x2D))
|
|
|
|
return 1;
|
|
|
|
if (_itemInHand != -1) {
|
|
|
|
assert(_putDownFirst);
|
|
|
|
characterSays(_putDownFirst[0], 0, -2);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (queryGameFlag(0xF1)) {
|
|
|
|
assert(_waitForAmulet);
|
|
|
|
characterSays(_waitForAmulet[0], 0, -2);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (!queryGameFlag(0x55+jewel)) {
|
|
|
|
assert(_blackJewel);
|
|
|
|
makeBrandonFaceMouse();
|
|
|
|
drawJewelPress(jewel, 1);
|
|
|
|
characterSays(_blackJewel[0], 0, -2);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
drawJewelPress(jewel, 0);
|
|
|
|
drawJewelsFadeOutStart();
|
|
|
|
drawJewelsFadeOutEnd(jewel);
|
|
|
|
|
|
|
|
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
|
|
|
|
_scriptClick->variables[3] = 0;
|
|
|
|
_scriptClick->variables[6] = jewel;
|
|
|
|
_scriptInterpreter->startScript(_scriptClick, 4);
|
|
|
|
|
|
|
|
while (_scriptInterpreter->validScript(_scriptClick)) {
|
|
|
|
_scriptInterpreter->runScript(_scriptClick);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_scriptClick->variables[3])
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
_unkAmuletVar = 1;
|
|
|
|
switch (jewel-1) {
|
|
|
|
case 0:
|
|
|
|
if (_brandonStatusBit & 1) {
|
2005-12-28 21:34:40 +00:00
|
|
|
seq_brandonHealing2();
|
2005-12-26 14:53:51 +00:00
|
|
|
} else if (_brandonStatusBit == 0) {
|
|
|
|
seq_brandonHealing();
|
|
|
|
assert(_healingTip);
|
|
|
|
characterSays(_healingTip[0], 0, -2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2005-12-29 22:18:40 +00:00
|
|
|
seq_makeBrandonInv();
|
2005-12-26 14:53:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2005-12-29 22:18:40 +00:00
|
|
|
if (_brandonStatusBit & 1) {
|
|
|
|
assert(_wispJewelStrings);
|
|
|
|
characterSays(_wispJewelStrings[0], 0, -2);
|
|
|
|
} else {
|
|
|
|
if (_brandonStatusBit & 2) {
|
|
|
|
// XXX
|
|
|
|
seq_makeBrandonNormal2();
|
|
|
|
// XXX
|
|
|
|
} else {
|
|
|
|
// do not check for item in hand again as in the original since some strings are missing
|
|
|
|
// in the cd version
|
|
|
|
if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
|
|
|
|
// XXX
|
|
|
|
seq_makeBrandonWisp();
|
|
|
|
// XXX
|
|
|
|
} else {
|
|
|
|
seq_makeBrandonWisp();
|
|
|
|
}
|
|
|
|
setGameFlag(0x9E);
|
|
|
|
}
|
|
|
|
}
|
2005-12-26 14:53:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2005-12-29 22:18:40 +00:00
|
|
|
seq_dispelMagicAnimation();
|
|
|
|
assert(_magicJewelString);
|
|
|
|
characterSays(_magicJewelString[0], 0, -2);
|
2005-12-26 14:53:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
_unkAmuletVar = 0;
|
|
|
|
// XXX clearKyrandiaButtonIO (!used before every return in this function!)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2005-12-24 18:00:35 +00:00
|
|
|
void KyraEngine::processButtonList(Button *list) {
|
|
|
|
while (list) {
|
|
|
|
if (list->flags & 8) {
|
|
|
|
list = list->nextButton;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = list->x;
|
|
|
|
int y = list->y;
|
|
|
|
assert(list->dimTableIndex < _screen->_screenDimTableCount);
|
|
|
|
if (x < 0) {
|
|
|
|
x += _screen->_screenDimTable[list->dimTableIndex].w << 3;
|
|
|
|
}
|
|
|
|
x += _screen->_screenDimTable[list->dimTableIndex].sx << 3;
|
|
|
|
|
|
|
|
if (y < 0) {
|
|
|
|
y += _screen->_screenDimTable[list->dimTableIndex].h;
|
|
|
|
}
|
|
|
|
y += _screen->_screenDimTable[list->dimTableIndex].sy;
|
|
|
|
|
|
|
|
if (_mouseX >= x && _mouseY >= y && x + list->width >= _mouseX && y + list->height >= _mouseY) {
|
|
|
|
int processMouseClick = 0;
|
|
|
|
if (list->flags & 0x400) {
|
|
|
|
if (_mousePressFlag) {
|
|
|
|
if (!(list->flags2 & 1)) {
|
|
|
|
list->flags2 |= 1;
|
|
|
|
processButton(list);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (list->flags2 & 1) {
|
|
|
|
list->flags2 &= 0xFFFE;
|
|
|
|
processButton(list);
|
|
|
|
processMouseClick = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (_mousePressFlag) {
|
|
|
|
processMouseClick = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processMouseClick) {
|
|
|
|
if (list->buttonCallback) {
|
|
|
|
if ((this->*(list->buttonCallback))(list)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (list->flags2 & 1) {
|
|
|
|
list->flags2 &= 0xFFFE;
|
|
|
|
processButton(list);
|
|
|
|
}
|
|
|
|
list = list->nextButton;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = list->nextButton;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine::processButton(Button *button) {
|
|
|
|
if (!button)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int processType = 0;
|
|
|
|
uint8 *shape = 0;
|
|
|
|
Button::ButtonCallback callback = 0;
|
|
|
|
|
|
|
|
int flags = (button->flags2 & 5);
|
|
|
|
if (flags == 1) {
|
|
|
|
processType = button->process2;
|
|
|
|
if (processType == 1) {
|
|
|
|
shape = button->process2PtrShape;
|
|
|
|
} else if (processType == 4) {
|
|
|
|
callback = button->process2PtrCallback;
|
|
|
|
}
|
|
|
|
} else if (flags == 4 || flags == 5) {
|
|
|
|
processType = button->process1;
|
|
|
|
if (processType == 1) {
|
|
|
|
shape = button->process1PtrShape;
|
|
|
|
} else if (processType == 4) {
|
|
|
|
callback = button->process1PtrCallback;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
processType = button->process0;
|
|
|
|
if (processType == 1) {
|
|
|
|
shape = button->process0PtrShape;
|
|
|
|
} else if (processType == 4) {
|
|
|
|
callback = button->process0PtrCallback;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = button->x;
|
|
|
|
int y = button->y;
|
|
|
|
assert(button->dimTableIndex < _screen->_screenDimTableCount);
|
|
|
|
if (x < 0) {
|
|
|
|
x += _screen->_screenDimTable[button->dimTableIndex].w << 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y < 0) {
|
|
|
|
y += _screen->_screenDimTable[button->dimTableIndex].h;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processType == 1 && shape) {
|
|
|
|
_screen->drawShape(_screen->_curPage, shape, x, y, button->dimTableIndex, 0x10);
|
|
|
|
} else if (processType == 4 && callback) {
|
|
|
|
(this->*callback)(button);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-19 22:12:09 +00:00
|
|
|
} // End of namespace Kyra
|