KYRA: (EOB) - initial code base commit

This commit is contained in:
athrxx 2011-12-11 01:57:03 +01:00 committed by Johannes Schickel
parent 9feb674e11
commit 540d081a6f
67 changed files with 20179 additions and 2372 deletions

3
configure vendored
View File

@ -94,8 +94,9 @@ add_engine gob "Gobli*ns" yes
add_engine groovie "Groovie" yes "groovie2"
add_engine groovie2 "Groovie 2 games" no
add_engine hugo "Hugo Trilogy" yes
add_engine kyra "Legend of Kyrandia" yes "lol"
add_engine kyra "Legend of Kyrandia" yes "lol eob"
add_engine lol "Lands of Lore" yes
add_engine eob "Eye of the Beholder" no
add_engine lastexpress "The Last Express" no
add_engine lure "Lure of the Temptress" yes
add_engine made "MADE" yes

View File

@ -87,6 +87,10 @@ MODULES += engines/kyra
ifdef ENABLE_LOL
DEFINES += -DENABLE_LOL
endif
ifdef ENABLE_EOB
DEFINES += -DENABLE_EOB
endif
endif
ifdef ENABLE_LASTEXPRESS

1495
engines/kyra/chargen.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,12 +17,15 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "kyra/kyra_lok.h"
#include "kyra/lol.h"
#include "kyra/kyra_hof.h"
#include "kyra/kyra_mr.h"
#include "kyra/eob1.h"
#include "kyra/eob2.h"
#include "common/config-manager.h"
#include "common/system.h"
@ -129,6 +132,14 @@ bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
*engine = new Kyra::LoLEngine(syst, flags);
break;
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
case Kyra::GI_EOB1:
*engine = new Kyra::EobEngine(syst, flags);
break;
case Kyra::GI_EOB2:
*engine = new Kyra::DarkMoonEngine(syst, flags);
break;
#endif // ENABLE_EOB
default:
res = false;
warning("Kyra engine: unknown gameID");

View File

@ -57,6 +57,9 @@ namespace {
#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, Kyra::GI_LOL)
#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB1)
#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB2)
const KYRAGameDescription adGameDescs[] = {
/* disable these targets until they get supported
{
@ -1439,6 +1442,73 @@ const KYRAGameDescription adGameDescs[] = {
LOL_KYRA2_DEMO_FLAGS
},
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
{
{
"eob",
0,
{
{ "EOBDATA2.PAK", 0, "feaf0345086b3a1d931352f4b0ad8feb", -1 },
{ 0, 0, 0, 0 }
},
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO3(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK)
},
EOB_FLAGS
},
{
{
"eob",
0,
{
{ "SHINDIA.CPS", 0, "383b0c7ba0903eae5d04cad28ce90aaf", -1 },
{ 0, 0, 0, 0 }
},
Common::DE_DEU,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO3(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK)
},
EOB_FLAGS
},
{
{
"eob2",
0,
{
{ "LEVEL15.INF", 0, "10f19eab75c73d0476dc58bcf70fff7a", -1 },
{ 0, 0, 0, 0 }
},
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO3(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK)
},
EOB2_FLAGS
},
{
{
"eob2",
0,
{
{ "LEVEL15.INF", 0, "ce54243ad1ca4447f521340428da2c91", -1 },
{ 0, 0, 0, 0 }
},
Common::DE_DEU,
Common::kPlatformPC,
ADGF_NO_FLAGS,
GUIO3(GUIO_NOSPEECH, GUIO_MIDIADLIB, GUIO_MIDIPCSPK)
},
EOB2_FLAGS
},
#endif // ENABLE_EOB
{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0) }
};
@ -1449,6 +1519,10 @@ const PlainGameDescriptor gameList[] = {
#ifdef ENABLE_LOL
{ "lol", "Lands of Lore: The Throne of Chaos" },
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
{ "eob", "Eye of the Beholder" },
{ "eob2", "Eye of the Beholder II: The Legend of Darkmoon" },
#endif // ENABLE_EOB
{ 0, 0 }
};

242
engines/kyra/eob1.cpp Normal file
View File

@ -0,0 +1,242 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#include "kyra/eob1.h"
#include "kyra/resource.h"
namespace Kyra {
EobEngine::EobEngine(OSystem *system, const GameFlags &flags) : EobCoreEngine(system, flags) {
_numSpells = 53;
}
EobEngine::~EobEngine() {
delete[] _itemsOverlay;
}
Common::Error EobEngine::init() {
Common::Error err = EobCoreEngine::init();
if (err.getCode() != Common::kNoError)
return err;
initStaticResource();
_itemsOverlay = _res->fileData("ITEMRMP.VGA", 0);
_bkgColor_1 = 132;
_color1_1 = 135;
_color2_1 = 130;
_color4 = 133;
_color5 = 133;
_color6 = 180;
_color7 = 177;
_color8 = 184;
_color14 = _color8;
_color13 = _color7;
_color12 = _color6;
_screen->modifyScreenDim(7, 0x01, 0xB3, 0x22, 0x12);
_screen->modifyScreenDim(9, 0x01, 0x7D, 0x26, 0x3F);
_screen->modifyScreenDim(12, 0x01, 0x04, 0x14, 0xA0);
_scriptTimersCount = 1;
return Common::kNoError;
}
void EobEngine::startupNew() {
_currentLevel = 1;
_currentSub = 0;
loadLevel(1, 0);
_currentBlock = 490;
_currentDirection = 0;
setHandItem(0);
}
void EobEngine::startupLoad() {
updateHandItemCursor();
loadLevel(_currentLevel, _currentSub);
_saveLoadMode = 0;
}
void EobEngine::npcSequence(int npcIndex) {
}
void EobEngine::updateUsedCharacterHandItem(int charIndex, int slot) {
EobItem *itm = &_items[_characters[charIndex].inventory[slot]];
if (itm->type == 48) {
int charges = itm->flags & 0x3f;
if (--charges)
--itm->flags;
else
deleteInventoryItem(charIndex, slot);
} else if (itm->type == 34 || itm->type == 35) {
deleteInventoryItem(charIndex, slot);
}
}
void EobEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
if (_levelBlockProperties[block].flags & 7)
return;
for (int i = 0; i < 30; i++) {
if (_monsters[i].hitPointsCur <= 0) {
initMonster(i, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);;
break;
}
}
}
void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {
_screen->loadEobBitmap("DOOR", 5, 3);
_screen->_curPage = 2;
if (doorType1 != 0xff) {
for (int i = 0; i < 3; i++) {
const uint8 *enc = &_doorShapeEncodeDefs[(doorType1 * 3 + i) << 2];
_doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
enc = &_doorSwitchShapeEncodeDefs[(doorType1 * 3 + i) << 2];
_doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
_doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 << 1];
_doorSwitches[shapeId1 + i].y = _doorSwitchCoords[(doorType1 << 1) + 1];
}
}
if (doorType2 != 0xff) {
for (int i = 0; i < 3; i++) {
const uint8 *enc = &_doorShapeEncodeDefs[(doorType2 * 3 + i) << 2];
_doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
enc = &_doorSwitchShapeEncodeDefs[(doorType2 * 3 + i) << 2];
_doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
_doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 << 1];
_doorSwitches[shapeId2 + i].y = _doorSwitchCoords[(doorType2 << 1) + 1];
}
}
_screen->_curPage = 0;
}
void EobEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wall, int mDim, int16 y1, int16 y2) {
int shapeIndex = type + 2 - mDim;
uint8 *shp = _doorShapes[shapeIndex];
int d1 = 0;
int d2 = 0;
int v = 0;
const ScreenDim *td = _screen->getScreenDim(5);
switch (_currentLevel) {
case 4:
case 5:
case 6:
y = _dscDoorY2[mDim] - shp[1];
d1 = _dscDoorCoordsExt[index << 1] >> 3;
d2 = _dscDoorCoordsExt[(index << 1) + 1] >> 3;
if (_shpDmX1 > d1)
d1 = _shpDmX1;
if (_shpDmX2 < d2)
d2 = _shpDmX2;
_screen->modifyScreenDim(5, d1, td->sy, d2 - d1, td->h);
v = ((wall < 30) ? (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim] : _dscDoorScaleMult4[mDim]) * -1;
v -= (shp[2] << 3);
drawBlockObject(0, 2, shp, x + v, y, 5);
v += (shp[2] << 3);
drawBlockObject(1, 2, shp, x - v, y, 5);
if (_wllShapeMap[wall] == -1)
drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w - v, _doorSwitches[shapeIndex].y, 5);
break;
case 7:
case 8:
case 9:
y = _dscDoorY3[mDim] - _doorShapes[shapeIndex + 3][1];
d1 = x - (_doorShapes[shapeIndex + 3][2] << 2);
x -= (shp[2] << 2);
drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], d1, y, 5);
scaleLevelShapesDim(index, y1, y2, 5);
y = _dscDoorY3[mDim] - ((wall < 30) ? (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim] : _dscDoorScaleMult2[mDim]);
drawBlockObject(0, 2, shp, x, y, 5);
if (_wllShapeMap[wall] == -1)
drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
break;
case 10:
case 11:
v = ((wall < 30) ? (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult5[mDim] : _dscDoorScaleMult6[mDim]) * -1;
x -= (shp[2] << 2);
y = _dscDoorY3[mDim] + v;
drawBlockObject(0, 2, shp, x, y + v, 5);
v >>= 4;
y = _dscDoorY5[mDim];
drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], x, y - v, 5);
if (_wllShapeMap[wall] == -1)
drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
break;
default:
y = (_currentLevel == 12 ? _dscDoorY6[mDim] : _dscDoorY1[mDim]) - shp[1];
x -= (shp[2] << 2);
y -= (wall >= 30 ? _dscDoorScaleMult2[mDim] : (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim]);
drawBlockObject(0, 2, shp, x, y, 5);
if (_wllShapeMap[wall] == -1)
drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
break;
}
}
uint32 EobEngine::convertSpellFlagToEob2Format(uint32 flag, int ignoreInvisibility) {
uint32 res = 0;
if (flag & 0x01)
res |= 0x20;
if (flag & 0x02)
res |= 0x400;
if (flag & 0x04)
res |= 0x80;
if (flag & 0x08)
res |= 0x40;
if (ignoreInvisibility)
res |= 0x100;
return res;
}
uint32 EobEngine::convertCharacterEffectFlagToEob2Format(uint32 flag) {
uint32 res = 0;
if (flag & 0x02)
res |= 0x08;
if (flag & 0x04)
res |= 0x40;
if (flag & 0x80)
res |= 0x2000;
if (flag & 0x100)
res |= 0x4000;
return res;
}
} // End of namespace Kyra
#endif // ENABLE_EOB

96
engines/kyra/eob1.h Normal file
View File

@ -0,0 +1,96 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#ifndef KYRA_EOB1_H
#define KYRA_EOB1_H
#include "kyra/eobcommon.h"
namespace Kyra {
class EobEngine : public EobCoreEngine {
friend class GUI_Eob;
public:
EobEngine(OSystem *system, const GameFlags &flags);
~EobEngine();
private:
// Init / Release
Common::Error init();
void initStaticResource();
void initSpells();
// Main Menu
int mainMenu();
int mainMenuLoop();
// Main loop
void startupNew();
void startupLoad();
// Intro/Outro
void seq_playOpeningCredits();
void seq_playIntro();
void seq_playFinale();
// characters
void npcSequence(int npcIndex);
//const char *const *_npc1Strings;
//const char *const *_npc2Strings;
// items
void updateUsedCharacterHandItem(int charIndex, int slot);
// Monsters
void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
// Level
void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2);
void drawDoorIntern(int type, int index, int x, int y, int w, int wall, int mDim, int16 y1, int16 y2);
const int16 *_dscDoorCoordsExt;
const uint8 *_dscDoorScaleMult4;
const uint8 *_dscDoorScaleMult5;
const uint8 *_dscDoorScaleMult6;
const uint8 *_dscDoorY3;
const uint8 *_dscDoorY4;
const uint8 *_dscDoorY5;
const uint8 *_dscDoorY6;
const uint8 *_doorShapeEncodeDefs;
const uint8 *_doorSwitchShapeEncodeDefs;
const uint8 *_doorSwitchCoords;
// Misc
uint32 convertSpellFlagToEob2Format(uint32 flag, int ignoreInvisibility);
uint32 convertCharacterEffectFlagToEob2Format(uint32 flag);
};
} // End of namespace Kyra
#endif
#endif // ENABLE_EOB

437
engines/kyra/eob2.cpp Normal file
View File

@ -0,0 +1,437 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#include "kyra/eob2.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
namespace Kyra {
DarkMoonEngine::DarkMoonEngine(OSystem *system, const GameFlags &flags) : EobCoreEngine(system, flags) {
_seqIntro = _seqFinale = 0;
_shapesIntro = _shapesFinale = 0;
_dscDoorType5Offs = 0;
_numSpells = 70;
}
DarkMoonEngine::~DarkMoonEngine() {
delete[] _seqIntro;
delete[] _seqFinale;
delete[] _shapesIntro;
delete[] _shapesFinale;
}
Common::Error DarkMoonEngine::init() {
Common::Error err = EobCoreEngine::init();
if (err.getCode() != Common::kNoError)
return err;
initStaticResource();
_monsterProps = new EobMonsterProperty[10];
_bkgColor_1 = 183;
_color1_1 = 186;
_color2_1 = 181;
_color4 = 133;
_color5 = 184;
_color6 = 183;
_color7 = 181;
_color8 = 186;
_color12 = 180;
_color13 = 177;
_color14 = 182;
return Common::kNoError;
}
void DarkMoonEngine::startupNew() {
_currentLevel = 4;
_currentSub = 0;
loadLevel(4, 0);
_currentBlock = 171;
_currentDirection = 2;
setHandItem(0);
}
void DarkMoonEngine::startupLoad() {
updateHandItemCursor();
loadLevel(_currentLevel, _currentSub);
_saveLoadMode = 0;
}
void DarkMoonEngine::npcSequence(int npcIndex) {
_screen->loadEobBitmap("OUTTAKE", 5, 3);
_screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK);
const uint8 *shpDef = &_npcShpData[npcIndex << 3];
for (int i = npcIndex; i != 255; i = shpDef[7]) {
shpDef = &_npcShpData[i << 3];
_screen->_curPage = 2;
const uint8 *shp = _screen->encodeShape(READ_LE_UINT16(shpDef), shpDef[2], shpDef[3], shpDef[4]);
_screen->_curPage = 0;
_screen->drawShape(0, shp, 88 + shpDef[5] - (shp[2] << 2), 104 + shpDef[6] - shp[1], 5);
delete[] shp;
}
Common::SeekableReadStream *s = _res->createReadStream("TEXT.DAT");
_screen->loadFileDataToPage(s, 5, 32000);
delete s;
gui_drawBox(0, 121, 320, 79, _color1_1, _color2_1, _bkgColor_1);
_txt->setupField(9, true);
_txt->resetPageBreakString();
if (npcIndex == 0) {
snd_playSoundEffect(57);
if (npcJoinDialogue(0, 1, 3, 2))
setScriptFlag(0x40);
} else if (npcIndex == 1) {
snd_playSoundEffect(53);
gui_drawDialogueBox();
_txt->printDialogueText(4, 0);
int r = runDialogue(-1, 0, _npc1Strings[0], _npc1Strings[1]) - 1;
if (r == 0) {
_sound->playTrack(0);
delay(3 * _tickLength);
snd_playSoundEffect(91);
npcJoinDialogue(1, 5, 6, 7);
} else if (r == 1) {
setScriptFlag(0x20);
}
} else if (npcIndex == 2) {
snd_playSoundEffect(55);
gui_drawDialogueBox();
_txt->printDialogueText(8, 0);
int r = runDialogue(-1, 0, _npc2Strings[0], _npc2Strings[1]) - 1;
if (r == 0) {
if (rollDice(1, 2, -1))
_txt->printDialogueText(9, _okStrings[0]);
else
npcJoinDialogue(2, 102, 103, 104);
setScriptFlag(8);
} else if (r == 1) {
_currentDirection = 0;
}
}
_txt->removePageBreakFlag();
gui_restorePlayField();
}
void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) {
EobItem *itm = &_items[_characters[charIndex].inventory[slot]];
if (itm->type == 48 || itm->type == 62) {
if (itm->value == 5)
return;
int charges = itm->flags & 0x3f;
if (--charges)
--itm->flags;
else
deleteInventoryItem(charIndex, slot);
} else if (itm->type == 26 || itm->type == 34 || itm->type == 35) {
deleteInventoryItem(charIndex, slot);
}
}
void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) {
int cp = _screen->setCurPage(2);
_screen->loadEobBitmap(file, 3, 3);
uint8 tmpPal[16];
uint8 newPal[16];
for (int i = 0; i < 6; i++) {
int dci = monsterIndex + i;
memcpy(tmpPal, _monsterShapes[dci] + 4, 16);
int colx = 302 + 3 * i;
for (int ii = 0; ii < 16; ii++) {
uint8 col = _screen->getPagePixel(_screen->_curPage, colx, 184 + ii);
int iii = 0;
for (; iii < 16; iii++) {
if (tmpPal[iii] == col) {
newPal[ii] = iii;
break;
}
}
if (iii == 16)
newPal[ii] = 0;
}
for (int ii = 1; ii < 3; ii++) {
memcpy(tmpPal, _monsterShapes[dci] + 4, 16);
for (int iii = 0; iii < 16; iii++) {
uint8 col = _screen->getPagePixel(_screen->_curPage, colx + ii, 184 + iii);
if (newPal[iii])
tmpPal[newPal[iii]] = col;
}
int c = i;
if (monsterIndex >= 18)
c += 6;
c = (c << 1) + (ii - 1);
memcpy(_monsterPalettes[c], tmpPal, 16);
}
}
_screen->setCurPage(cp);
}
void DarkMoonEngine::loadMonsterDecoration(const char *file, int16 monsterIndex) {
char filename[13];
snprintf(filename, 13, "%s.dcr", file);
Common::SeekableReadStream *s = _res->createReadStream(filename);
if (!s)
return;
int len = s->readUint16LE();
for (int i = 0; i < len; i++) {
for (int ii = 0; ii < 6; ii++) {
uint8 dc[6];
s->read(dc, 6);
if (!dc[2] || !dc[3])
continue;
SpriteDecoration *m = &_monsterDecorations[i * 6 + ii + monsterIndex];
m->shp = _screen->encodeShape(dc[0], dc[1], dc[2], dc[3]);
m->x = dc[4];
m->y = dc[5];
}
}
delete s;
}
void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
uint8 flg = _levelBlockProperties[block].flags & 7;
if (flg == 7 || _currentBlock == block || (flg && (_monsterProps[type].u30 || pos == 4)))
return;
for (int i = 0; i < 30; i++) {
if (_monsters[i].block != block)
continue;
if (_monsters[i].pos == 4 || _monsterProps[_monsters[i].type].u30)
return;
}
int index = -1;
int maxDist = 0;
for (int i = 0; i < 30; i++) {
if (_monsters[i].hitPointsCur <= 0) {
index = i;
break;
}
if (_monsters[i].flags & 0x40)
continue;
int dist = getBlockDistance(_monsters[i].block, _currentBlock);
if (dist > maxDist) {
maxDist = dist;
index = i;
}
}
if (index == -1)
return;
if (_monsters[index].hitPointsCur > 0)
killMonster(&_monsters[index], false);
initMonster(index, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);
}
const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) {
_screen->loadEobBitmap(filename, 3, 3);
for (int i = 0; i < 3; i++) {
_doorShapes[doorIndex * 3 + i] = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6));
shapeDefs += 8;
}
for (int i = 0; i < 2; i++) {
_doorSwitches[doorIndex * 3 + i].shp = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6));
shapeDefs += 8;
_doorSwitches[doorIndex * 3 + i].x = *shapeDefs;
shapeDefs += 2;
_doorSwitches[doorIndex * 3 + i]. y= *shapeDefs;
shapeDefs += 2;
}
_screen->_curPage = 0;
return shapeDefs;
}
void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16) {
int shapeIndex = type * 3 + 2 - mDim;
uint8 *shp = _doorShapes[shapeIndex];
if ((_doorType[type] == 0) || (_doorType[type] == 1)) {
y = _dscDoorY1[mDim] - shp[1];
x -= (shp[2] << 2);
if (_doorType[type] == 1) {
drawBlockObject(0, 2, shp, x, y, 5);
shp = _doorShapes[3 + shapeIndex];
}
y -= ((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim]);
if (_specialWallTypes[wall] == 5)
y -= _dscDoorType5Offs[shapeIndex];
} else if (_doorType[type] == 2) {
x -= (shp[2] << 2);
y = _dscDoorY2[mDim] - ((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim]);
}
drawBlockObject(0, 2, shp, x, y, 5);
if (_wllShapeMap[wall] == -1 && !_noDoorSwitch[type])
drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
}
void DarkMoonEngine::drawLightningColumn() {
int f = rollDice(1, 2, -1);
int y = 0;
for (int i = 0; i < 6; i++) {
f ^= 1;
drawBlockObject(f, 2, _lightningColumnShape, 72, y, 5);
y += 64;
}
}
int DarkMoonEngine::resurrectionSelectDialogue() {
int cnt = 0;
const char *namesList[10];
memset(namesList, 0, 10 * sizeof(const char*));
int8 indexList[10];
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
if (_characters[i].hitPointsCur != -10)
continue;
namesList[cnt] = _characters[i].name;
indexList[cnt++] = i;
}
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
for (int ii = 0; ii < 27; ii++) {
uint16 inv = _characters[i].inventory[ii];
if (!inv)
continue;
if (_items[inv].type != 33)
continue;
namesList[cnt] = _npcPreset[_items[inv].value - 1].name;
indexList[cnt++] = -_items[inv].value;
}
}
if (_itemInHand) {
if (_items[_itemInHand].type == 33) {
namesList[cnt] = _npcPreset[_items[_itemInHand].value - 1].name;
indexList[cnt++] = -_items[_itemInHand].value;
}
}
namesList[cnt] = _abortStrings[0];
indexList[cnt++] = 99;
int r = indexList[runDialogue(-1, 1, namesList[0], namesList[1], namesList[2], namesList[3], namesList[4], namesList[5], namesList[6], namesList[7], namesList[8]) - 1];
if (r == 99)
return 0;
if (r < 0) {
r = -r;
if (prepareForNewPartyMember(33, r))
initNpc(r - 1);
} else {
_characters[r].hitPointsCur = 1;
}
return 1;
}
int DarkMoonEngine::charSelectDialogue() {
int cnt = 0;
const char *namesList[7];
memset(namesList, 0, 7 * sizeof(const char*));
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 3))
continue;
namesList[cnt++] = _characters[i].name;
}
namesList[cnt++] = _abortStrings[0];
int r = runDialogue(-1, 1, namesList[0], namesList[1], namesList[2], namesList[3], namesList[4], namesList[5], namesList[6], 0) - 1;
if (r == cnt - 1)
return 99;
for (cnt = 0; cnt < 6; cnt++) {
if (!testCharacter(cnt, 3))
continue;
if (--r < 0)
break;
}
return cnt;
}
void DarkMoonEngine::characterLevelGain(int charIndex) {
EobCharacter *c = &_characters[charIndex];
int s = _numLevelsPerClass[c->cClass];
for (int i = 0; i < s; i++) {
uint32 er = getRequiredExperience(c->cClass, i, c->level[i] + 1);
if (er == 0xffffffff)
continue;
increaseCharacterExperience(charIndex, er - c->experience[i]);
}
}
} // End of namespace Kyra
#endif // ENABLE_EOB

119
engines/kyra/eob2.h Normal file
View File

@ -0,0 +1,119 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#ifndef KYRA_EOB2_H
#define KYRA_EOB2_H
#include "kyra/eobcommon.h"
namespace Kyra {
class DarkmoonSequenceHelper;
struct EobSequenceStep {
uint8 command;
uint8 obj;
int16 x1;
uint8 y1;
uint8 delay;
uint8 pal;
uint8 x2;
uint8 y2;
uint8 w;
uint8 h;
};
class DarkMoonEngine : public EobCoreEngine {
friend class GUI_Eob;
friend class DarkmoonSequenceHelper;
public:
DarkMoonEngine(OSystem *system, const GameFlags &flags);
~DarkMoonEngine();
private:
// Init / Release
Common::Error init();
void initStaticResource();
void initSpells();
// Main Menu
int mainMenu();
int mainMenuLoop();
// Main loop
void startupNew();
void startupLoad();
// Intro/Outro
void seq_playIntro();
void seq_playFinale();
void seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *data, int sd, int backupPage, int tempPage, int speed);
const char * const*_introStrings;
const char * const *_cpsFilesIntro;
const EobSequenceStep **_seqIntro;
const EobShapeDef **_shapesIntro;
const char * const*_finaleStrings;
const uint8 *_creditsData;
const char * const *_cpsFilesFinale;
const EobSequenceStep **_seqFinale;
const EobShapeDef **_shapesFinale;
static const char *_palFilesIntro[];
static const char *_palFilesFinale[];
// characters
void npcSequence(int npcIndex);
const uint8 *_npcShpData;
const char *const *_npc1Strings;
const char *const *_npc2Strings;
// items
void updateUsedCharacterHandItem(int charIndex, int slot);
// Monsters
void generateMonsterPalettes(const char *file, int16 monsterIndex);
void loadMonsterDecoration(const char *file, int16 monsterIndex);
void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
// Level
const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs);
void drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16);
const uint8 *_dscDoorType5Offs;
// misc
void drawLightningColumn();
int resurrectionSelectDialogue();
int charSelectDialogue();
void characterLevelGain(int charIndex);
};
} // End of namespace Kyra
#endif
#endif // ENABLE_EOB

1845
engines/kyra/eobcommon.cpp Normal file

File diff suppressed because it is too large Load Diff

977
engines/kyra/eobcommon.h Normal file
View File

@ -0,0 +1,977 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef KYRA_EOBCOMMON_H
#define KYRA_EOBCOMMON_H
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/loleobbase.h"
#endif // (ENABLE_EOB || ENABLE_LOL)
#ifdef ENABLE_EOB
namespace Kyra {
struct EobShapeDef {
int16 index;
uint8 x, y, w, h;
};
struct CreatePartyModButton {
uint8 encodeLabelX;
uint8 encodeLabelY;
uint8 labelW;
uint8 labelH;
uint8 labelX;
uint8 labelY;
uint8 bodyIndex;
uint8 destX;
uint8 destY;
};
struct EobRect8 {
uint8 x;
uint8 y;
uint8 w;
uint8 h;
};
struct EobRect16 {
int16 x1;
int16 y1;
uint16 x2;
uint16 y2;
};
struct EobChargenButtonDef {
uint8 x;
uint8 y;
uint8 w;
uint8 h;
uint8 keyCode;
};
struct EobGuiButtonDef {
uint8 keyCode;
uint8 keyCode2;
uint16 flags;
uint16 x;
uint8 y;
uint16 w;
uint8 h;
Button::Callback buttonCallback;
uint16 arg;
};
struct EobCharacter {
uint8 id;
uint8 flags;
char name[11];
int8 strengthCur;
int8 strengthMax;
int8 strengthExtCur;
int8 strengthExtMax;
int8 intelligenceCur;
int8 intelligenceMax;
int8 wisdomCur;
int8 wisdomMax;
int8 dexterityCur;
int8 dexterityMax;
int8 constitutionCur;
int8 constitutionMax;
int8 charismaCur;
int8 charismaMax;
int16 hitPointsCur;
int16 hitPointsMax;
int8 armorClass;
uint8 disabledSlots;
uint8 raceSex;
uint8 cClass;
uint8 alignment;
int8 portrait;
uint8 food;
uint8 level[3];
uint32 experience[3];
uint8 *faceShape;
int8 mageSpells[80];
int8 clericSpells[80];
uint32 mageSpellsAvailabilityFlags;
Item inventory[27];
uint32 timers[10];
int8 events[10];
uint8 effectsRemainder[4];
uint32 effectFlags;
uint8 damageTaken;
int8 slotStatus[5];
};
struct EobItem {
uint8 nameUnid;
uint8 nameId;
uint8 flags;
int8 icon;
int8 type;
int8 pos;
int16 block;
Item next;
Item prev;
uint8 level;
int8 value;
};
struct EobItemType {
uint16 invFlags;
uint16 handFlags;
int8 armorClass;
int8 allowedClasses;
int8 requiredHands;
int8 dmgNumDiceS;
int8 dmgNumPipsS;
int8 dmgIncS;
int8 dmgNumDiceL;
int8 dmgNumPipsL;
int8 dmgIncL;
uint8 unk1;
uint16 extraProperties;
};
struct SpriteDecoration {
uint8 *shp;
uint8 x;
uint8 y;
};
struct EobMonsterProperty {
int8 armorClass;
int8 hitChance;
uint8 level;
uint8 hpDcTimes;
uint8 hpDcPips;
uint8 hpDcBase;
uint8 attacksPerRound;
struct DmgDc {
uint8 times;
uint8 pips;
int8 base;
} dmgDc[3];
uint16 statusFlags;
uint16 flags;
int32 u22;
int32 experience;
uint8 u30;
uint8 sound1;
uint8 sound2;
uint8 numRemoteAttacks;
uint8 remoteWeaponChangeMode;
uint8 numRemoteWeapons;
int8 remoteWeapons[5];
uint8 u41;
uint8 dmgModifierEvade;
uint8 decorations[3];
};
struct EobMonsterInPlay {
uint8 type;
uint8 unit;
uint16 block;
uint8 pos;
int8 dir;
uint8 animStep;
uint8 shpIndex;
int8 mode;
int8 f_9;
int8 curAttackFrame;
uint8 f_b;
int16 hitPointsMax;
int16 hitPointsCur;
uint16 dest;
uint16 randItem;
uint16 fixedItem;
uint8 flags;
uint8 idleAnimState;
uint8 curRemoteWeapon;
uint8 numRemoteAttacks;
int8 palette;
uint8 directionChanged;
uint8 stepsTillRemoteAttack;
uint8 sub;
};
struct ScriptTimer {
uint16 func;
uint16 ticks;
uint32 next;
};
struct EobFlyingObject {
uint8 enable;
uint8 objectType;
int16 attackerId;
Item item;
uint16 curBlock;
uint16 u2;
uint8 u1;
uint8 direction;
uint8 distance;
int8 callBackIndex;
uint8 curPos;
uint8 flags;
uint8 unused;
};
class EobInfProcessor;
class EobCoreEngine : public LolEobBaseEngine {
friend class TextDisplayer_Eob;
friend class GUI_Eob;
friend class EobInfProcessor;
friend class DarkmoonSequenceHelper;
friend class CharacterGenerator;
public:
EobCoreEngine(OSystem *system, const GameFlags &flags);
virtual ~EobCoreEngine();
Screen *screen() { return _screen; }
GUI *gui() const { return _gui; }
protected:
// Startup
virtual Common::Error init();
Common::Error go();
// Main Menu, Intro, Finale
virtual int mainMenu() = 0;
virtual void seq_playFinale() = 0;
bool _playFinale;
//Init
void loadItemsAndDecorationsShapes();
void releaseItemsAndDecorationsShapes();
void initButtonData();
void initStaticResource();
virtual void initSpells();
const uint8 **_largeItemShapes;
const uint8 **_smallItemShapes;
const uint8 **_thrownItemShapes;
const int _numLargeItemShapes;
const int _numSmallItemShapes;
const int _numThrownItemShapes;
const int _numItemIconShapes;
const uint8 **_spellShapes;
const uint8 **_firebeamShapes;
const uint8 *_redSplatShape;
const uint8 *_greenSplatShape;
const uint8 **_wallOfForceShapes;
const uint8 **_teleporterShapes;
const uint8 **_sparkShapes;
const uint8 *_deadCharShape;
const uint8 *_disabledCharGrid;
const uint8 *_blackBoxSmallGrid;
const uint8 *_weaponSlotGrid;
const uint8 *_blackBoxWideGrid;
const uint8 *_lightningColumnShape;
uint8 *_tempIconShape;
uint8 *_itemsOverlay;
static const uint8 _teleporterShapeDefs[];
static const uint8 _wallOfForceShapeDefs[];
const char *const *_mainMenuStrings;
// Main loop
virtual void startupNew() = 0;
virtual void startupLoad() = 0;
void runLoop();
void update() { screen()->updateScreen(); }
bool updateCharacterEvents(bool a);
bool _runFlag;
//int _runLoopUnk2;
// Create Party
void startCharacterGeneration();
uint8 **_faceShapes;
static const int8 _classHpIncreaseType[];
static const uint8 _hpIncrPerLevel[];
static const uint8 _numLevelsPerClass[];
static const int16 _hpConstModifiers[];
static const uint8 _charClassModUnk[];
const uint8 *_classModifierFlags;
// timers
void setupTimers();
void setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer);
void deleteCharEventTimer(int charIndex, int evnt);
void setupCharacterTimers();
void timerProcessMonsters(int timerNum);
void timerSpecialCharacterUpdate(int timerNum);
void timerProcessFlyingObjects(int timerNum);
void timerProcessCharacterExchange(int timerNum);
void timerUpdateTeleporters(int timerNum);
void timerUpdateFoodStatus(int timerNum);
void timerUpdateMonsterIdleAnim(int timerNum);
uint8 getClock2Timer(int index) { return index < _numClock2Timers ? _clock2Timers[index] : 0; }
uint8 getNumClock2Timers() { return _numClock2Timers; }
static const uint8 _clock2Timers[];
static const uint8 _numClock2Timers;
// Mouse
void setHandItem(Item itemIndex);
void updateHandItemCursor() { _updateHandItemCursor = true; }
bool _updateHandItemCursor;
// Characters
int getDexterityArmorClassModifier(int dexterity);
int generateCharacterHitpointsByLevel(int charIndex, int levelIndex);
int getClassAndConstHitpointsModifier(int cclass, int constitution);
int getClassHpIncreaseType(int cclass, int levelIndex);
int getModifiedHpLimits(int hpModifier, int constModifier, int level, bool mode);
const char *getCharStrength(int str, int strExt);
int testCharacter(int index, int flags);
int getNextValidCharIndex(int curCharIndex, int searchStep);
void recalcArmorClass(int index);
int validateWeaponSlotItem(int index, int slot);
int getCharacterClericPaladinLevel(int index);
int getCharacterMageLevel(int index);
int getLevelIndexForHpIncType(int unk, int cClass);
int countCharactersWithSpecificItems(int16 itemType, int16 itemValue);
int checkCharacterInventoryForItem(int character, int16 itemType, int16 itemValue);
void modifyCharacterHitpoints(int character, int16 points);
void neutralizePoison(int character);
virtual void npcSequence(int npcIndex) = 0;
void initNpc(int npcIndex);
int npcJoinDialogue(int npcIndex, int queryJoinTextId, int confirmJoinTextId, int noJoinTextId);
int prepareForNewPartyMember(int16 itemType, int16 itemValue);
void removeCharacterFromParty(int charIndex);
void increasePartyExperience(int16 points);
void increaseCharacterExperience(int charIndex, int32 points);
uint32 getRequiredExperience(int cClass, int levelIndex, int level);
void increaseCharacterLevel(int charIndex, int levelIndex);
void setWeaponSlotStatus(int charIndex, int mode, int slot);
EobCharacter *_characters;
char _strenghtStr[6];
int _castScrollSlot;
int _exchangeCharacterId;
const char *const *_levelGainStrings;
const uint32 *_expRequirementTables[6];
const uint8 *_constModTables[6];
const uint8 *_constModLevelIndex;
const uint8 *_constModDiv;
const uint8 *_constModExt;
const EobCharacter *_npcPreset;
bool _partyResting;
// Items
void loadItemDefs();
Item duplicateItem(Item itemIndex);
void setItemPosition(Item *itemQueue, int block, Item item, int pos);
void createInventoryItem(EobCharacter *c, Item itemIndex, int itemValue, int preferedInventorySlot);
int deleteInventoryItem(int charIndex, int slot);
void deleteBlockItem(uint16 block, int type);
int validateInventorySlotForItem(Item item, int charIndex, int slot);
void deletePartyItem(Item itemType, int16 itemValue);
virtual void updateUsedCharacterHandItem(int charIndex, int slot) = 0;
int itemUsableByCharacter(int charIndex, Item item);
int countQueuedItems(Item itemQueue, int16 id, int16 type, int count, int includeFlyingItems);
int getQueuedItem(Item *items, int pos, int id);
void printFullItemName(Item item);
void identifyQueuedItems(Item itemQueue);
void drawItemIconShape(int pageNum, Item itemId, int x, int y);
bool isMagicWeapon(Item itemIndex);
bool checkInventoryForRings(int charIndex, int itemValue);
void eatItemInHand(int charIndex);
bool launchObject(int charIndex, Item item, uint16 startBlock, int startPos, int dir, int type);
void launchMagicObject(int charIndex, int type, uint16 startBlock, int startPos, int dir);
bool updateObjectFlight(EobFlyingObject *fo, int block, int pos);
bool updateFlyingObjectHitTest(EobFlyingObject *fo, int block, int pos);
void updateFlyingObject_s3(EobFlyingObject *fo);
void endObjectFlight(EobFlyingObject *fo);
void checkFlyingObjects();
void reloadWeaponSlot(int charIndex, int slotIndex, int itemType, int arrowOrDagger);
EobItem *_items;
uint16 _numItems;
EobItemType *_itemTypes;
char **_itemNames;
uint16 _numItemNames;
uint32 _partyEffectFlags;
Item _lastUsedItem;
const uint16 *_slotValidationFlags;
EobFlyingObject *_flyingObjects;
const uint8 *_drawObjPosIndex;
const uint8 *_flightObjFlipIndex;
const int8 *_flightObjShpMap;
const int8 *_flightObjSclIndex;
// Monsters
void loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex);
void releaseMonsterShapes(int first, int num);
virtual void generateMonsterPalettes(const char *file, int16 monsterIndex) {}
virtual void loadMonsterDecoration(const char *file, int16 monsterIndex) {}
const uint8 *loadMonsterProperties(const uint8 *data);
const uint8 *loadActiveMonsterData(const uint8 *data, int level);
void initMonster(int index, int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int i, int randItem, int fixedItem);
void placeMonster(EobMonsterInPlay *m, uint16 block, int dir);
virtual void replaceMonster(int b, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) = 0;
void killMonster(EobMonsterInPlay *m, bool giveExperience);
int countSpecificMonsters(int type);
void updateAttackingMonsterFlags();
const int8 *getMonsterBlockPositions(uint16 block);
int getClosestMonsterPos(int charIndex, int block);
bool blockHasMonsters(uint16 block);
bool isMonsterOnPos(EobMonsterInPlay *m, uint16 block, int pos, int checkPos4);
const int16 *findBlockMonsters(uint16 block, int pos, int dir, int blockDamage, int singleTargetCheckAdjacent);
void drawBlockObject(int flipped, int page, const uint8 *shape, int x, int y, int sd, uint8 *ovl = 0);
void drawMonsterShape(const uint8 *shape, int x, int y, int flipped, int flags, int palIndex);
void flashMonsterShape(EobMonsterInPlay *m);
void updateAllMonsterShapes();
void drawBlockItems(int index);
void drawDoor(int index);
virtual void drawDoorIntern(int type, int index, int x, int y, int w, int wall, int mDim, int16 y1, int16 y2) = 0;
void drawMonsters(int index);
void drawWallOfForce(int index);
void drawFlyingObjects(int index);
void drawTeleporter(int index);
void updateMonsters(int unit);
void updateMonsterDest(EobMonsterInPlay *m);
void updateMonsterDest2(EobMonsterInPlay *m);
void turnFriendlyMonstersHostile();
int getNextMonsterDirection(int curBlock, int destBlock);
int getNextMonsterPos(EobMonsterInPlay *m, int block);
int findFreeMonsterPos(int block, int size);
void updateMoveMonster(EobMonsterInPlay *m);
bool updateMonsterTryDistanceAttack(EobMonsterInPlay *m);
bool updateMonsterTryCloseAttack(EobMonsterInPlay *m, int block);
void walkMonster(EobMonsterInPlay *m, int destBlock);
bool walkMonsterNextStep(EobMonsterInPlay *m, int destBlock, int direction);
void updateMonsterFollowPath(EobMonsterInPlay *m, int turnSteps);
void updateMonstersStraying(EobMonsterInPlay *m, int a);
void updateMonsters_mode710(EobMonsterInPlay *m);
void setBlockMonsterDirection(int block, int dir);
uint8 *_monsterOvl1;
uint8 *_monsterOvl2;
SpriteDecoration *_monsterDecorations;
EobMonsterProperty *_monsterProps;
EobMonsterInPlay *_monsters;
const int8 *_monsterStepTable0;
const int8 *_monsterStepTable1;
const int8 *_monsterStepTable2;
const int8 *_monsterStepTable3;
const uint8 *_monsterCloseAttPosTable1;
const uint8 *_monsterCloseAttPosTable2;
const int8 *_monsterCloseAttUnkTable;
const uint8 *_monsterCloseAttChkTable1;
const uint8 *_monsterCloseAttChkTable2;
const uint8 *_monsterCloseAttDstTable1;
const uint8 *_monsterCloseAttDstTable2;
const uint8 *_monsterProximityTable;
const uint8 *_findBlockMonstersTable;
const char *const *_monsterDustStrings;
const uint8 *_monsterDistAttType10;
const uint8 *_monsterDistAttSfx10;
const uint8 *_monsterDistAttType17;
const uint8 *_monsterDistAttSfx17;
const char *const *_monsterSpecAttStrings;
const int8 *_monsterFrmOffsTable1;
const int8 *_monsterFrmOffsTable2;
const uint16 *_encodeMonsterShpTable;
const uint8 _teleporterWallId;
const int8 *_monsterDirChangeTable;
// Level
void loadLevel(int level, int func);
const char *initLevelData(int func);
void addLevelItems();
void loadVcnData(const char *file, const char */*nextFile*/);
void loadBlockProperties(const char *mazFile);
void loadDecorations(const char *cpsFile, const char *decFile);
void assignWallsAndDecorations(int wallIndex, int vmpIndex, int decDataIndex, int specialType, int flags);
void releaseDecorations();
void releaseDoorShapes();
void toggleWallState(int wall, int flags);
virtual void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {}
virtual const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8*shapeDefs) { return (const uint8*)filename; }
void drawScene(int update);
void drawSceneShapes();
void drawDecorations(int index);
int calcNewBlockPositionAndTestPassability(uint16 curBlock, uint16 direction);
void notifyBlockNotPassable();
void moveParty(uint16 block);
int clickedDoorSwitch(uint16 block, uint16 direction);
int clickedDoorPry(uint16 block, uint16 direction);
int clickedDoorNoPry(uint16 block, uint16 direction);
int clickedNiche(uint16 block, uint16 direction);
int specialWallAction(int block, int direction);
void openDoor(int block);
void closeDoor(int block);
int16 _doorType[2];
int16 _noDoorSwitch[2];
EobRect8 *_levelDecorationRects;
SpriteDecoration *_doorSwitches;
int8 _currentSub;
char _curGfxFile[13];
uint32 _drawSceneTimer;
uint32 _flashShapeTimer;
uint32 _envAudioTimer;
uint16 _teleporterPulse;
const int16 *_dscShapeCoords;
const uint8 *_dscItemPosIndex;
const int16 *_dscItemShpX;
const uint8 *_dscItemScaleIndex;
const uint8 *_dscItemTileIndex;
const uint8 *_dscItemShapeMap;
const uint8 *_dscDoorScaleOffs;
const uint8 *_dscDoorScaleMult1;
const uint8 *_dscDoorScaleMult2;
const uint8 *_dscDoorScaleMult3;
const uint8 *_dscDoorY1;
const uint8 *_wllFlagPreset;
int _wllFlagPresetSize;
const uint8 *_teleporterShapeCoords;
// Script
void runLevelScript(int block, int flags);
void setScriptFlag(int flag);
bool checkScriptFlag(int flag);
const uint8 *initScriptTimers(const uint8 *pos);
void updateScriptTimers();
EobInfProcessor *_inf;
int _stepCounter;
int _stepsUntilScriptCall;
ScriptTimer _scriptTimers[5];
int _scriptTimersCount;
uint8 _scriptTimersMode;
// Gui
void gui_drawPlayField(int pageNum);
void gui_restorePlayField();
void gui_drawAllCharPortraitsWithStats();
void gui_drawCharPortraitWithStats(int index);
void gui_drawFaceShape(int index);
void gui_drawWeaponSlot(int charIndex, int slot);
void gui_drawWeaponSlotStatus(int x, int y, int status);
void gui_drawHitpoints(int index);
void gui_drawFoodStatusGraph(int index);
void gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2);
void gui_drawCharPortraitStatusFrame(int index);
void gui_drawInventoryItem(int slot, int special, int pageNum);
void gui_drawCompass(bool force);
void gui_drawDialogueBox();
void gui_drawSpellbook();
void gui_drawSpellbookScrollArrow(int x, int y, int direction);
void gui_updateSlotAfterScrollUse();
void gui_updateControls();
void gui_toggleButtons();
void gui_setPlayFieldButtons();
void gui_setInventoryButtons();
void gui_setStatsListButtons();
void gui_setSwapCharacterButtons();
void gui_setCastOnWhomButtons();
void gui_initButton(int index, int x = -1, int y = -1, int val = -1);
Button *gui_getButton(Button *buttonList, int index);
int clickedInventoryNextPage(Button *button);
int clickedPortraitRestore(Button *button);
int clickedCharPortraitDefault(Button *button);
int clickedCamp(Button *button);
int clickedSceneDropPickupItem(Button *button);
int clickedCharPortrait2(Button *button);
int clickedWeaponSlot(Button *button);
int clickedCharNameLabelRight(Button *button);
int clickedInventorySlot(Button *button);
int clickedEatItem(Button *button);
int clickedInventoryPrevChar(Button *button);
int clickedInventoryNextChar(Button *button);
int clickedSpellbookTab(Button *button);
int clickedSpellbookList(Button *button);
int clickedCastSpellOnCharacter(Button *button);
int clickedUpArrow(Button *button);
int clickedDownArrow(Button *button);
int clickedLeftArrow(Button *button);
int clickedRightArrow(Button *button);
int clickedTurnLeftArrow(Button *button);
int clickedTurnRightArrow(Button *button);
int clickedAbortCharSwitch(Button *button);
int clickedSceneThrowItem(Button *button);
int clickedSceneSpecial(Button *button);
int clickedSpellbookAbort(Button *button);
int clickedSpellbookScroll(Button *button);
int clickedUnk(Button *button);
void gui_processCharPortraitClick(int index);
void gui_processWeaponSlotClickLeft(int charIndex, int slotIndex);
void gui_processWeaponSlotClickRight(int charIndex, int slotIndex);
void gui_processInventorySlotClick(int slot);
static const int16 _buttonList1[];
int _buttonList1Size;
static const int16 _buttonList2[];
int _buttonList2Size;
static const int16 _buttonList3[];
int _buttonList3Size;
static const int16 _buttonList4[];
int _buttonList4Size;
static const int16 _buttonList5[];
int _buttonList5Size;
static const int16 _buttonList6[];
int _buttonList6Size;
static const int16 _buttonList7[];
int _buttonList7Size;
static const int16 _buttonList8[];
int _buttonList8Size;
const EobGuiButtonDef *_buttonDefs;
const char *const *_characterGuiStringsHp;
const char *const *_characterGuiStringsWp;
const char *const *_characterGuiStringsWr;
const char *const *_characterGuiStringsSt;
const char *const *_characterGuiStringsIn;
const char *const *_characterStatusStrings7;
const char *const *_characterStatusStrings8;
const char *const *_characterStatusStrings9;
const char *const *_characterStatusStrings12;
const char *const *_characterStatusStrings13;
const uint16 *_inventorySlotsX;
const uint8 *_inventorySlotsY;
const uint8 **_compassShapes;
uint8 _charExchangeSwap;
bool _hpBarGraphs;
// text
void setupDialogueButtons(int presetfirst, int numStr, const char *str1, ...);
void initDialogueSequence();
void restoreAfterDialogueSequence();
void drawSequenceBitmap(const char *file, int destRect, int x1, int y1, int flags);
int runDialogue(int dialogueTextId, int style, const char *button1, ...);
char _dialogueLastBitmap[13];
int _dlgUnk1;
int _moveCounter;
uint8 _color4;
uint8 _color5;
uint8 _color6;
uint8 _color7;
uint8 _color8;
uint8 _color9;
uint8 _color10;
uint8 _color11;
uint8 _color12;
uint8 _color13;
uint8 _color14;
const char *const *_chargenStatStrings;
const char *const *_chargenRaceSexStrings;
const char *const *_chargenClassStrings;
const char *const *_chargenAlignmentStrings;
const char *const *_pryDoorStrings;
const char *const *_warningStrings;
const char *const *_itemExtraStrings;
const char *const *_itemSuffixStrings;
const char *const *_takenStrings;
const char *const *_potionEffectStrings;
const char *const *_yesNoStrings;
const char *const *_npcMaxStrings;
const char *const *_okStrings;
const char *const *_npcJoinStrings;
const char *const *_cancelStrings;
const char *const *_abortStrings;
// misc
void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false);
void displayParchment(int id);
virtual void drawLightningColumn() {}
virtual int resurrectionSelectDialogue() { return -1; }
virtual int charSelectDialogue() { return -1; }
virtual void characterLevelGain(int charIndex) {}
Common::Error loadGameState(int slot);
Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail);
void *generateMonsterTempData(LevelTempData *tmp);
void *generateFlyingObjectTempData(LevelTempData *tmp);
void restoreMonsterTempData(LevelTempData *tmp);
void restoreFlyingObjectTempData(LevelTempData *tmp);
void releaseMonsterTempData(LevelTempData *tmp);
void releaseFlyingObjectTempData(LevelTempData *tmp);
int _saveLoadMode;
Screen_Eob *_screen;
GUI_Eob *_gui;
// fight
void useSlotWeapon(int charIndex, int slotIndex, int item);
int closeDistanceAttack(int charIndex, int item);
int thrownAttack(int charIndex, int slotIndex, int item);
int bowAttack(int charIndex, int item);
void inflictMonsterDamage(EobMonsterInPlay *m, int damage, bool giveExperience);
void calcAndInflictMonsterDamage(EobMonsterInPlay *m, int times, int pips, int offs, int flags, int b, int damageType);
void calcAndInflictCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flg, int a, int damageType);
int calcCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flg, int a, int damageType) ;
void inflictCharacterDamage(int charIndex, int damage);
bool characterAttackHitTest(int charIndex, int monsterIndex, int item, int attackType);
bool monsterAttackHitTest(EobMonsterInPlay *m, int charIndex);
bool flyingObjectMonsterHit(EobFlyingObject *fo, int monsterIndex);
bool flyingObjectPartyHit(EobFlyingObject *fo);
void monsterCloseAttack(EobMonsterInPlay *m);
void monsterSpellCast(EobMonsterInPlay *m, int type);
void statusAttack(int charIndex, int attackStatusFlags, const char *attackStatusString, int a, uint32 effectDuration, int restoreEvent, int noRefresh);
int calcCloseDistanceMonsterDamage(EobMonsterInPlay *m, int times, int pips, int offs, int flags, int b, int damageType);
int calcDamageModifers(int charIndex, EobMonsterInPlay *m, int item, int itemType, int useStrModifier);
bool checkUnkConstModifiers(void *target, int hpModifier, int level, int b, int race);
bool specialAttackConstTest(int charIndex, int b);
int getConstModifierTableValue(int hpModifier, int level, int b);
bool calcDamageCheckItemType(int itemType);
int recalcDamageModifier(int damageType, int dmgModifier);
bool checkMonsterDamageEvasion(EobMonsterInPlay *m);
int getStrHitChanceModifier(int charIndex);
int getStrDamageModifier(int charIndex);
int getDexHitChanceModifier(int charIndex);
int getMonsterAcHitChanceModifier(int charIndex, int monsterAc);
void inflictMonsterDamage_s1(EobMonsterInPlay *m);
int _dstMonsterIndex;
int _inflictMonsterDamageUnk;
int16 _foundMonstersArray[5];
// magic
void useMagicBookOrSymbol(int charIndex, int type);
void useMagicScroll(int charIndex, int type, int weaponSlot);
void usePotion(int charIndex, int weaponSlot);
void castSpell(int spell, int weaponSlot);
void removeCharacterEffect(int spell, int charIndex, int showWarning);
void removeAllCharacterEffects(int charIndex);
void castOnWhomDialogue();
void startSpell(int spell);
void sparkEffectDefensive(int charIndex);
void sparkEffectOffensive();
void setSpellEventTimer(int spell, int timerBaseFactor, int timerLength, int timerLevelFactor, int updateExistingTimer);
bool magicObjectHit(EobFlyingObject *fo, int dcTimes, int dcPips, int dcOffs, int level);
void spellCallback_start_empty() {}
bool spellCallback_end_empty(EobFlyingObject *fo) { return true; }
void spellCallback_start_armor();
void spellCallback_start_burningHands();
void spellCallback_start_detectMagic();
bool spellCallback_end_detectMagic(EobFlyingObject *fo);
void spellCallback_start_magicMissile();
bool spellCallback_end_magicMissile(EobFlyingObject *fo);
void spellCallback_start_shockingGrasp();
bool spellCallback_end_shockingGraspFlameBlade(EobFlyingObject *fo);
void spellCallback_start_improvedIdentify();
void spellCallback_start_melfsAcidArrow();
bool spellCallback_end_melfsAcidArrow(EobFlyingObject *fo);
void spellCallback_start_dispelMagic();
void spellCallback_start_fireball();
bool spellCallback_end_fireball(EobFlyingObject *fo);
void spellCallback_start_flameArrow();
bool spellCallback_end_flameArrow(EobFlyingObject *fo);
void spellCallback_start_holdPerson();
bool spellCallback_end_holdPerson(EobFlyingObject *fo);
void spellCallback_start_lightningBolt();
bool spellCallback_end_lightningBolt(EobFlyingObject *fo);
void spellCallback_start_vampiricTouch();
bool spellCallback_end_vampiricTouch(EobFlyingObject *fo);
void spellCallback_start_fear();
void spellCallback_start_iceStorm();
bool spellCallback_end_iceStorm(EobFlyingObject *fo);
void spellCallback_start_removeCurse();
void spellCallback_start_coneOfCold();
void spellCallback_start_holdMonster();
bool spellCallback_end_holdMonster(EobFlyingObject *fo);
void spellCallback_start_wallOfForce();
void spellCallback_start_disintegrate();
void spellCallback_start_fleshToStone();
void spellCallback_start_stoneToFlesh();
void spellCallback_start_trueSeeing();
bool spellCallback_end_trueSeeing(EobFlyingObject *fo);
void spellCallback_start_slayLiving();
void spellCallback_start_powerWordStun();
void spellCallback_start_causeLightWounds();
void spellCallback_start_cureLightWounds();
void spellCallback_start_aid();
bool spellCallback_end_aid(EobFlyingObject *fo);
void spellCallback_start_flameBlade();
void spellCallback_start_slowPoison();
bool spellCallback_end_slowPoison(EobFlyingObject *fo);
void spellCallback_start_createFood();
void spellCallback_start_removeParalysis();
void spellCallback_start_causeSeriousWounds();
void spellCallback_start_cureSeriousWounds();
void spellCallback_start_neutralizePoison();
void spellCallback_start_causeCriticalWounds();
void spellCallback_start_cureCriticalWounds();
void spellCallback_start_flameStrike();
bool spellCallback_end_flameStrike(EobFlyingObject *fo);
void spellCallback_start_raiseDead();
void spellCallback_start_harm();
void spellCallback_start_heal();
void spellCallback_start_layOnHands();
void spellCallback_start_turnUndead();
bool spellCallback_end_unk1Passive(EobFlyingObject *fo);
bool spellCallback_end_unk2Passive(EobFlyingObject *fo);
bool spellCallback_end_deathSpellPassive(EobFlyingObject *fo);
bool spellCallback_end_disintegratePassive(EobFlyingObject *fo);
bool spellCallback_end_causeCriticalWoundsPassive(EobFlyingObject *fo);
bool spellCallback_end_fleshToStonePassive(EobFlyingObject *fo);
int8 _openBookSpellLevel;
int8 _openBookSpellSelectedItem;
int8 _openBookSpellListOffset;
uint8 _openBookChar;
uint8 _openBookType;
uint8 _openBookCharBackup;
uint8 _openBookTypeBackup;
const char *const *_openBookSpellList;
int8 *_openBookAvailableSpells;
uint8 _activeSpellCaster;
uint8 _activeSpellCasterPos;
uint8 _activeSpell;
bool _returnAfterSpellCallback;
typedef void (EobCoreEngine::*SpellStartCallback)();
typedef bool (EobCoreEngine::*SpellEndCallback)(EobFlyingObject *fo);
struct EobSpell {
const char *name;
SpellStartCallback startCallback;
uint16 flags;
const uint16 *timingPara;
SpellEndCallback endCallback;
uint8 sound;
uint32 effectFlags;
uint16 damageFlags;
};
EobSpell *_spells;
int _numSpells;
const char *const *_bookNumbers;
const char *const *_mageSpellList;
int _mageSpellListSize;
int _clericSpellOffset;
const char *const *_clericSpellList;
const char *const *_spellNames;
const char *const *_magicStrings1;
const char *const *_magicStrings2;
const char *const *_magicStrings3;
const char *const *_magicStrings4;
const char *const *_magicStrings5;
const char *const *_magicStrings6;
const char *const *_magicStrings7;
const char *const *_magicStrings8;
uint8 *_spellAnimBuffer;
const uint8 *_sparkEffectDefSteps;
const uint8 *_sparkEffectDefSubSteps;
const uint8 *_sparkEffectDefShift;
const uint8 *_sparkEffectDefAdd;
const uint8 *_sparkEffectDefX;
const uint8 *_sparkEffectDefY;
const uint32 *_sparkEffectOfFlags1;
const uint32 *_sparkEffectOfFlags2;
const uint8 *_sparkEffectOfShift;
const uint8 *_sparkEffectOfX;
const uint8 *_sparkEffectOfY;
const uint8 *_magicFlightObjectProperties;
// sound
void snd_playSoundEffect(int id, int volume=0xFF);
};
} // End of namespace Kyra
#endif // ENABLE_EOB
#endif

View File

@ -40,10 +40,10 @@ struct Button {
typedef Common::Functor1<Button *, int> CallbackFunctor;
typedef Common::SharedPtr<CallbackFunctor> Callback;
Button() : nextButton(0), index(0), keyCode(0), keyCode2(0), data0Val1(0), data1Val1(0), data2Val1(0), flags(0),
Button() : nextButton(0), index(0), keyCode(0), keyCode2(0), data0Val1(0), data1Val1(0), data2Val1(0), data3Val1(0), flags(0),
data0ShapePtr(0), data1ShapePtr(0), data2ShapePtr(0), data0Callback(), data1Callback(), data2Callback(),
dimTableIndex(0), x(0), y(0), width(0), height(0), data0Val2(0), data0Val3(0), data1Val2(0), data1Val3(0),
data2Val2(0), data2Val3(0), flags2(0), mouseWheel(0), buttonCallback(), arg(0) {}
data2Val2(0), data2Val3(0), data3Val2(0), data3Val3(0), flags2(0), mouseWheel(0), buttonCallback(), arg(0) {}
Button *nextButton;
uint16 index;
@ -54,6 +54,7 @@ struct Button {
byte data0Val1;
byte data1Val1;
byte data2Val1;
byte data3Val1;
uint16 flags;
@ -78,6 +79,9 @@ struct Button {
uint8 data2Val2;
uint8 data2Val3;
uint8 data3Val2;
uint8 data3Val3;
uint16 flags2;
int8 mouseWheel;

2165
engines/kyra/gui_eob.cpp Normal file

File diff suppressed because it is too large Load Diff

130
engines/kyra/gui_eob.h Normal file
View File

@ -0,0 +1,130 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#ifndef KYRA_GUI_EOB_H
#define KYRA_GUI_EOB_H
#include "kyra/gui.h"
#ifdef ENABLE_EOB
namespace Kyra {
class DarkMoonEngine;
class Screen_Eob;
class GUI_Eob : public GUI {
friend class EobCoreEngine;
friend class CharacterGenerator;
public:
GUI_Eob(EobCoreEngine *vm);
void initStaticData() {}
// button specific
void processButton(Button *button);
int processButtonList(Button *buttonList, uint16 inputFlags, int8 mouseWheel);
int redrawShadedButtonCallback(Button *button) { return 0; }
int redrawButtonCallback(Button *button) { return 0; }
void setupMenu(int sd, int maxItem, const char *const *strings, int32 menuItemsMask, int unk, int lineSpacing);
int handleMenu(int sd, const char *const *strings, void *b, int32 menuItemsMask, int unk);
int getMenuItem(int index, int32 menuItemsMask, int unk);
void menuFlashSelection(const char *str, int x, int y, int color1, int color2, int color3);
int getTextInput(char *dest, int x, int y, int destMaxLen, int textColor1, int textColor2, int cursorColor);
//int runMenu(Menu &menu);
// utilities for thumbnail creation
void createScreenThumbnail(Graphics::Surface &dst) {}
private:
void initMenuItemsMask(int menuId, int maxItem, int32 menuItemsMask, int unk);
//void backupPage0();
//void restorePage0();
//void setupSavegameNames(Menu &menu, int num);
//void printMenuText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 flags);
//int getMenuCenterStringX(const char *str, int x1, int x2);
int getInput();
Button *getButtonListData() { return _menuButtons; }
Button *getScrollUpButton() { return &_scrollUpButton; }
Button *getScrollDownButton() { return &_scrollDownButton; }
Button::Callback getScrollUpButtonHandler() const { return _scrollUpFunctor; }
Button::Callback getScrollDownButtonHandler() const { return _scrollDownFunctor; }
uint8 defaultColor1() const { return 0xFE; }
uint8 defaultColor2() const { return 0x00; }
const char *getMenuTitle(const Menu &menu) { return 0; }
const char *getMenuItemTitle(const MenuItem &menuItem) { return 0; }
const char *getMenuItemLabel(const MenuItem &menuItem) { return 0; }
Button _menuButtons[10];
Button _scrollUpButton;
Button _scrollDownButton;
//Menu _mainMenu, _gameOptions, _audioOptions, _choiceMenu, _loadMenu, _saveMenu, _deleteMenu, _savenameMenu, _deathMenu;
//Menu *_currentMenu, *_lastMenu, *_newMenu;
//int _menuResult;
//char *_saveDescription;
EobCoreEngine *_vm;
Screen_Eob *_screen;
bool _pressFlag;
Button *_specialProcessButton;
Button *_backupButtonList;
uint16 _flagsMouseLeft;
uint16 _flagsMouseRight;
uint16 _flagsModifier;
uint16 _progress;
uint16 _prcButtonUnk3; /// ALWAYS 1?? REMOVE ??
uint16 _cflag;
Button::Callback _scrollUpFunctor;
Button::Callback _scrollDownFunctor;
int _menuLineSpacing;
int _menuUnk1;
int _menuLastInFlags;
int _menuCur;
int _menuNumItems;
};
} // End of namespace Kyra
#endif // ENABLE_EOB
#endif
#endif // ENABLE_EOB || ENABLE_LOL

View File

@ -32,6 +32,7 @@
#include "common/savefile.h"
#include "common/system.h"
#include "common/config-manager.h"
#include "graphics/scaler.h"
#include "base/version.h"
@ -213,9 +214,9 @@ void LoLEngine::gui_displayCharInventory(int charNum) {
}
if (_flags.use16ColorMode)
gui_drawBarGraph(154, 66 + i * 8, 34, 5, b, e, 0x88, 0);
gui_drawHorizontalBarGraph(154, 66 + i * 8, 34, 5, b, e, 0x88, 0);
else
gui_drawBarGraph(154, 64 + i * 10, 34, 5, b, e, 132, 0);
gui_drawHorizontalBarGraph(154, 64 + i * 10, 34, 5, b, e, 132, 0);
}
_screen->drawClippedLine(14, 120, 194, 120, 1);
@ -343,31 +344,6 @@ void LoLEngine::gui_drawCharInventoryItem(int itemIndex) {
_screen->drawShape(_screen->_curPage, getItemIconShapePtr(i), x + 1, y + 1, 0, 0);
}
void LoLEngine::gui_drawBarGraph(int x, int y, int w, int h, int32 cur, int32 max, int col1, int col2) {
if (max < 1)
return;
if (cur < 0)
cur = 0;
int32 e = MIN(cur, max);
if (!--w)
return;
if (!--h)
return;
int32 t = (e * w) / max;
if (!t && e)
t++;
if (t)
_screen->fillRect(x, y, x + t - 1, y + h, col1);
if (t < w && col2)
_screen->fillRect(x + t, y, x + w, y + h, col2);
}
void LoLEngine::gui_drawAllCharPortraitsWithStats() {
int numChars = countActiveCharacters();
if (!numChars)
@ -460,17 +436,6 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) {
_screen->setFont(tmpFid);
}
void LoLEngine::gui_drawBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor) {
w--; h--;
if (fillColor != -1)
_screen->fillRect(x + 1, y + 1, x + w - 1, y + h - 1, fillColor);
_screen->drawClippedLine(x + 1, y, x + w, y, frameColor2);
_screen->drawClippedLine(x + w, y, x + w, y + h - 1, frameColor2);
_screen->drawClippedLine(x, y, x, y + h, frameColor1);
_screen->drawClippedLine(x, y + h, x + w, y + h, frameColor1);
}
void LoLEngine::gui_drawCharFaceShape(int charNum, int x, int y, int pageNum) {
if (_characters[charNum].curFaceFrame < 7 && _characters[charNum].tempFaceFrame)
_characters[charNum].curFaceFrame = _characters[charNum].tempFaceFrame;
@ -853,19 +818,6 @@ void LoLEngine::gui_triggerEvent(int eventType) {
_preserveEvents = true;
}
void LoLEngine::removeInputTop() {
if (!_eventList.empty()) {
if (_eventList.begin()->event.type == Common::EVENT_LBUTTONDOWN)
_gui->_mouseClick = 1;
else if (_eventList.begin()->event.type == Common::EVENT_RBUTTONDOWN)
_gui->_mouseClick = 2;
else
_gui->_mouseClick = 0;
_eventList.erase(_eventList.begin());
}
}
void LoLEngine::gui_enableDefaultPlayfieldButtons() {
gui_resetButtonList();
gui_initButtonsFromList(_buttonList1);
@ -911,19 +863,6 @@ void LoLEngine::gui_enableCharInventoryButtons(int charNum) {
gui_setFaceFramesControlButtons(21, 0);
}
void LoLEngine::gui_resetButtonList() {
for (uint i = 0; i < ARRAYSIZE(_activeButtonData); ++i)
_activeButtonData[i].nextButton = 0;
gui_notifyButtonListChanged();
_activeButtons = 0;
}
void LoLEngine::gui_initButtonsFromList(const int16 *list) {
while (*list != -1)
gui_initButton(*list++);
}
void LoLEngine::gui_setFaceFramesControlButtons(int index, int xOffs) {
int c = countActiveCharacters();
for (int i = 0; i < c; i++)
@ -1009,14 +948,6 @@ void LoLEngine::gui_initButton(int index, int x, int y, int val) {
b->buttonCallback = _buttonCallbacks[index];
}
void LoLEngine::gui_notifyButtonListChanged() {
if (_gui) {
if (!_gui->_buttonListChanged && !_preserveEvents)
removeInputTop();
_gui->_buttonListChanged = true;
}
}
int LoLEngine::clickedUpArrow(Button *button) {
if (button->arg && !_floatingCursorsEnabled)
return 0;
@ -1333,7 +1264,6 @@ int LoLEngine::clickedExitCharInventory(Button *button) {
int LoLEngine::clickedSceneDropItem(Button *button) {
static const uint8 offsX[] = { 0x40, 0xC0, 0x40, 0xC0 };
static const uint8 offsY[] = { 0x40, 0x40, 0xC0, 0xC0 };
static const uint8 dirIndex[] = { 0, 1, 2, 3, 1, 3, 0, 2, 3, 2, 1, 0, 2, 0, 3, 1 };
if ((_updateFlags & 1) || !_itemInHand)
return 0;
@ -1348,7 +1278,7 @@ int LoLEngine::clickedSceneDropItem(Button *button) {
uint16 x = 0;
uint16 y = 0;
int i = dirIndex[(_currentDirection << 2) + button->arg];
int i = _dropItemDirIndex[(_currentDirection << 2) + button->arg];
calcCoordinates(x, y, block, offsX[i], offsY[i]);
setItemPosition(_itemInHand, x, y, 0, 1);
@ -1917,9 +1847,7 @@ GUI_LoL::GUI_LoL(LoLEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
_specialProcessButton = _backUpButtonList = 0;
_flagsModifier = 0;
_mouseClick = 0;
_sliderSfx = 11;
_buttonListChanged = false;
_savegameList = 0;
_savegameListSize = 0;
}
@ -2015,18 +1943,18 @@ int GUI_LoL::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseW
if (!buttonList)
return inputFlag & 0x7FFF;
if (_backUpButtonList != buttonList || _buttonListChanged) {
if (_backUpButtonList != buttonList || _vm->_buttonListChanged) {
_specialProcessButton = 0;
_flagsModifier = 0;
if (_mouseClick == 1)
if (_vm->_mouseClick == 1)
_flagsModifier |= 0x200;
if (_mouseClick == 2)
if (_vm->_mouseClick == 2)
_flagsModifier |= 0x2000;
_mouseClick = 0;
_vm->_mouseClick = 0;
_backUpButtonList = buttonList;
_buttonListChanged = false;
_vm->_buttonListChanged = false;
while (buttonList) {
processButton(buttonList);

View File

@ -162,9 +162,7 @@ private:
Button *_specialProcessButton;
Button *_backUpButtonList;
bool _buttonListChanged;
uint16 _flagsModifier;
uint8 _mouseClick;
int _savegameOffset;
int _sliderSfx;

614
engines/kyra/items_eob.cpp Normal file
View File

@ -0,0 +1,614 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#include "kyra/eobcommon.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
namespace Kyra {
void EobCoreEngine::loadItemDefs() {
Common::SeekableReadStream *s = _res->createReadStream("item.dat");
_numItems = s->readUint16LE();
for (int i = 0; i < 600; i++)
_items[i].block = -1;
for (int i = 0; i < _numItems; i++) {
_items[i].nameUnid = s->readByte();
_items[i].nameId = s->readByte();
_items[i].flags = s->readByte();
_items[i].icon = s->readSByte();
_items[i].type = s->readSByte();
_items[i].pos = s->readSByte();
_items[i].block = s->readSint16LE();
_items[i].next = s->readSint16LE();
_items[i].prev = s->readSint16LE();
_items[i].level = s->readSByte();
_items[i].value = s->readSByte();
}
_numItemNames = s->readUint16LE();
for (int i = 0; i < _numItemNames; i++)
s->read(_itemNames[i], 35);
delete s;
s = _res->createReadStream("itemtype.dat");
uint16 numTypes = s->readUint16LE();
_itemTypes = new EobItemType[numTypes];
memset(_itemTypes, 0, sizeof(EobItemType) * numTypes);
for (int i = 0; i < numTypes; i++) {
_itemTypes[i].invFlags = s->readUint16LE();
_itemTypes[i].handFlags = s->readUint16LE();
_itemTypes[i].armorClass = s->readSByte();
_itemTypes[i].allowedClasses = s->readSByte();
_itemTypes[i].requiredHands = s->readSByte();
_itemTypes[i].dmgNumDiceS = s->readSByte();
_itemTypes[i].dmgNumPipsS = s->readSByte();
_itemTypes[i].dmgIncS = s->readSByte();
_itemTypes[i].dmgNumDiceL = s->readSByte();
_itemTypes[i].dmgNumPipsL = s->readSByte();
_itemTypes[i].dmgIncL = s->readSByte();
_itemTypes[i].unk1 = s->readByte();
_itemTypes[i].extraProperties = s->readUint16LE();
}
delete s;
}
Kyra::Item EobCoreEngine::duplicateItem(Item itemIndex) {
EobItem *itm = &_items[itemIndex];
if (itm->block == -1)
return 0;
Item i = 1;
bool foundSlot = false;
for (; i < 600; i++) {
if (_items[i].block == -1) {
foundSlot = true;
break;
}
}
if (!foundSlot)
return 0;
memcpy(&_items[i], &_items[itemIndex], sizeof(EobItem));
return i;
}
void EobCoreEngine::setItemPosition(Item *itemQueue, int block, Item item, int pos) {
if (!item)
return;
EobItem *itm = &_items[item];
itm->pos = pos;
itm->block = block;
itm->level = block < 0 ? 0xff : _currentLevel;
if (!*itemQueue) {
*itemQueue = itm->next = itm->prev = item;
} else {
EobItem *itmQ = &_items[*itemQueue];
EobItem *itmQN = &_items[itmQ->next];
itm->prev = itmQN->prev;
itm->next = itmQ->next;
*itemQueue = itmQN->prev = itmQ->next = item;
}
}
void EobCoreEngine::createInventoryItem(EobCharacter *c, Item itemIndex, int itemValue, int preferedInventorySlot) {
if (itemIndex <= 0)
return;
itemIndex = duplicateItem(itemIndex);
_items[itemIndex].flags |= 0x40;
if (itemValue != -1)
_items[itemIndex].value = itemValue;
if (itemValue && ((_itemTypes[_items[itemIndex].type].extraProperties & 0x7f) < 4))
_items[itemIndex].flags |= 0x80;
if (c->inventory[preferedInventorySlot]) {
for (int i = 2; i < 16; i++) {
if (!c->inventory[i]) {
c->inventory[i] = itemIndex;
return;
}
}
} else {
c->inventory[preferedInventorySlot] = itemIndex;
}
}
int EobCoreEngine::deleteInventoryItem(int charIndex, int slot) {
int itm = (slot == -1) ? _itemInHand : _characters[charIndex].inventory[slot];
_items[itm].block = -1;
if (slot == -1) {
setHandItem(0);
} else {
_characters[charIndex].inventory[slot] = 0;
if (_currentControlMode == 1)
gui_drawInventoryItem(slot, 1, 0);
if (_currentControlMode == 0)
gui_drawCharPortraitWithStats(charIndex);
}
return _items[itm].value;
}
void EobCoreEngine::deleteBlockItem(uint16 block, int type) {
uint16 itm = _levelBlockProperties[block].drawObjects;
if (!itm)
return;
for (uint16 i2 = itm, i = 0; itm != i2 || !i; i++ ) {
if (type == _items[itm].type || type == -1) {
_items[itm].block = -1;
_items[itm].level = 0;
uint16 i3 = itm;
itm = _items[itm].prev;
_items[i3].prev = _items[i3].next = 0;
} else {
uint16 i3 = itm;
itm = _items[itm].prev;
_items[i3].prev = _items[i3].next = 0;
setItemPosition((Item*)&_levelBlockProperties[block].drawObjects, block, i3, _items[i3].pos);
}
}
}
int EobCoreEngine::validateInventorySlotForItem(Item item, int charIndex, int slot) {
if (item < 0)
return 0;
int offset = (_flags.gameID == GI_EOB1) ? 11 : (_flags.lang == Common::DE_DEU ? 16 : 12);
if (slot == 17 && item && !itemUsableByCharacter(charIndex, item)) {
_txt->printMessage(_itemExtraStrings[offset], -1, _characters[charIndex].name);
return 0;
}
int itm = _characters[charIndex].inventory[slot];
int ex = _itemTypes[_items[itm].type].extraProperties & 0x7f;
if (slot < 2 && _items[itm].flags & 0x20 && ex > 0 && ex < 4) {
_txt->printMessage(_itemExtraStrings[offset + 1], -1, _characters[charIndex].name);
return 0;
}
uint16 v = item ? _itemTypes[_items[item].type].invFlags : 0xffff;
if (v & _slotValidationFlags[slot])
return 1;
_txt->printMessage(_itemExtraStrings[offset + (_flags.gameID == GI_EOB1 ? 1 : 2)]);
return 0;
}
void EobCoreEngine::deletePartyItem(Item itemType, int16 itemValue) {
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
EobCharacter *c = &_characters[i];
int slot = checkCharacterInventoryForItem(i, itemType, itemValue);
if (slot == -1)
continue;
int itm = c->inventory[slot];
_items[itm].block = -1;
c->inventory[slot] = 0;
if (_currentControlMode == 0 && slot < 2 && i < 5)
gui_drawWeaponSlot(i, slot);
if (_currentControlMode == 1 && i == _updateCharNum)
gui_drawInventoryItem(slot, 1, 0);
}
}
int EobCoreEngine::itemUsableByCharacter(int charIndex, Item item) {
if (!item)
return 1;
return (_itemTypes[_items[item].type].allowedClasses & _classModifierFlags[_characters[charIndex].cClass]);
}
int EobCoreEngine::countQueuedItems(Item itemQueue, int16 id, int16 type, int count, int includeFlyingItems) {
uint16 o1 = itemQueue;
uint16 o2 = o1;
if (!o1)
return 0;
int res = 0;
for (bool forceLoop = true; o1 != o2 || forceLoop; o1 = _items[o1].prev) {
EobItem *itm = &_items[o1];
forceLoop = false;
if (id != -1 || type != -1) {
if ((id != -1 || (id == -1 && type != itm->type)) && (type != -1) || (id != o1))
continue;
}
if (!includeFlyingItems) {
if (itm->pos > 3 && itm->pos < 8)
continue;
}
if (!count)
return o1;
res++;
}
return res;
}
int EobCoreEngine::getQueuedItem(Item *items, int pos, int id) {
Item o1 = *items;
Item o2 = o1;
if (!o1)
return 0;
EobItem *itm = &_items[o1];
for (bool forceLoop = true; o1 != o2 || forceLoop; o1 = itm->prev) {
itm = &_items[o1];
forceLoop = false;
if ((id != -1 || (id == -1 && itm->pos != pos)) && id != o1)
continue;
Item n = itm->next;
Item p = itm->prev;
_items[n].prev = p;
_items[p].next = n;
itm->next = itm->prev = itm->block = 0;
itm->level = 0;
if (o1 == *items)
*items = p;
if (o1 == *items)
*items = 0;
return o1;
}
return 0;
}
void EobCoreEngine::printFullItemName(Item item) {
EobItem *itm = &_items[item];
const char *nameUnid = _itemNames[itm->nameUnid];
const char *nameId = _itemNames[itm->nameId];
uint8 f = _itemTypes[itm->type].extraProperties & 0x7f;
int8 v = itm->value;
const char *tstr2 = 0;
const char *tstr3 = 0;
int e = 0;
char tmpString[61];
if ((itm->flags & 0x40) && !strlen(nameId)) {
switch (f) {
case 0:
case 1:
case 2:
case 3:
if (v == 0)
strcpy(tmpString, nameUnid);
else if (v < 0)
sprintf(tmpString, _itemExtraStrings[3], v, nameUnid);
else
sprintf(tmpString, _itemExtraStrings[4], v, nameUnid);
break;
case 9:
tstr2 = _itemExtraStrings[5];
tstr3 = _spells[v].name;
e = 1;
break;
case 10:
tstr2 = _itemExtraStrings[6];
tstr3 = _spells[_flags.gameID == GI_EOB1 ? (_clericSpellOffset + v) : v].name;
e = 1;
break;
case 14:
tstr2 = _itemExtraStrings[8];
tstr3 = _itemSuffixStrings[8];
break;
case 16:
tstr2 = _itemExtraStrings[7];
tstr3 = _itemSuffixStrings[v + 6];
e = 0;
break;
case 18:
if (v == 5) {
tstr2 = _itemExtraStrings[_flags.lang == Common::EN_ANY ? 9 : 10];
e = 1;
} else {
tstr2 = _itemExtraStrings[9];
e = 0;
}
tstr3 = _itemSuffixStrings[v + (_flags.lang == Common::EN_ANY ? 11 : 15)];
break;
default:
strcpy(tmpString, nameUnid);
break;
}
if (tstr3) {
if (!tstr2) {
sprintf(tmpString, _itemExtraStrings[_flags.lang == Common::EN_ANY ? 10 : 11], tstr3);
} else {
if (e == 1) {
if (tstr2 == _itemExtraStrings[12])
sprintf(tmpString, _itemExtraStrings[_flags.lang == Common::EN_ANY ? 11 : 14], tstr2, tstr3);
else
sprintf(tmpString, _itemExtraStrings[_flags.gameID == GI_EOB1 ? 10 : (_flags.lang == Common::EN_ANY ? 11 : 13)], tstr2, tstr3);
} else {
sprintf(tmpString, _itemExtraStrings[_flags.gameID == GI_EOB1 ? 10 : (_flags.lang == Common::EN_ANY ? 11 : 15)], tstr2, tstr3);
}
}
}
} else {
strcpy(tmpString, (itm->flags & 0x40) ? nameId : nameUnid);
}
_txt->printMessage(tmpString);
}
void EobCoreEngine::identifyQueuedItems(Item itemQueue) {
if (!itemQueue)
return;
Item first = itemQueue;
do {
_items[itemQueue].flags |= 0x40;
itemQueue = _items[itemQueue].prev;
} while (first != itemQueue);
}
void EobCoreEngine::drawItemIconShape(int pageNum, Item itemId, int x, int y) {
int icn = _items[itemId].icon;
bool applyBluePal = ((_partyEffectFlags & 2) && (_items[itemId].flags & 0x80)) ? true : false;
if (applyBluePal) {
_screen->setFadeTableIndex(3);
_screen->setShapeFadeMode(1, true);
}
_screen->drawShape(pageNum, _itemIconShapes[icn], x, y, 0);
if (applyBluePal) {
_screen->setFadeTableIndex(4);
_screen->setShapeFadeMode(1, false);
}
}
bool EobCoreEngine::isMagicWeapon(Item itemIndex) {
return (_items[itemIndex].type > 10 && _items[itemIndex].type < 18);
}
bool EobCoreEngine::checkInventoryForRings(int charIndex, int itemValue) {
for (int i = 25; i <= 26; i++) {
int itm = _characters[charIndex].inventory[i];
if (itm && _items[itm].type == 47 && _items[itm].value == itemValue)
return true;
}
return false;
}
void EobCoreEngine::eatItemInHand(int charIndex) {
EobCharacter *c = &_characters[charIndex];
if (!testCharacter(charIndex, 5)) {
_txt->printMessage(_warningStrings[1], -1, c->name);
} else if (_itemInHand && _items[_itemInHand].type != 31) {
_txt->printMessage(_warningStrings[3]);
} else if (_items[_itemInHand].value == -1) {
_txt->printMessage(_warningStrings[2]);
snd_playSoundEffect(79);
} else {
c->food += _items[_itemInHand].value;
if (c->food > 100)
c->food = 100;
_items[_itemInHand].block = -1;
setHandItem(0);
gui_drawFoodStatusGraph(charIndex);
_screen->updateScreen();
snd_playSoundEffect(9);
}
}
bool EobCoreEngine::launchObject(int charIndex, Item item, uint16 startBlock, int startPos, int dir, int type) {
EobFlyingObject *t = _flyingObjects;
int slot = 0;
for (; slot < 10; slot++) {
if (!t->enable)
break;
t++;
}
if (slot == 10)
return false;
setItemPosition((Item*)&_levelBlockProperties[startBlock].drawObjects, startBlock, item, startPos | 4);
t->enable = 1;
t->u2 = 1;
t->flags = 0;
t->direction = dir;
t->distance = 12;
t->curBlock = startBlock;
t->curPos = startPos;
t->item = item;
t->objectType = type;
t->attackerId = charIndex;
t->callBackIndex = 0;
snd_playSoundEffect(type == 7 ? 26 : 11);
return true;
}
void EobCoreEngine::launchMagicObject(int charIndex, int type, uint16 startBlock, int startPos, int dir) {
EobFlyingObject *t = _flyingObjects;
int slot = 0;
for (; slot < 10; slot++) {
if (!t->enable)
break;
t++;
}
if (slot == 10)
return;
t->enable = 2;
t->u2 = 1;
t->flags = _magicFlightObjectProperties[(type << 2) + 2];
t->direction = dir;
t->distance = _magicFlightObjectProperties[(type << 2) + 1];
t->curBlock = startBlock;
t->curPos = startPos;
t->item = type;
t->objectType = _magicFlightObjectProperties[(type << 2) + 3];
t->attackerId = charIndex;
t->u2 = 1;
t->callBackIndex = _magicFlightObjectProperties[type << 2];
_sceneUpdateRequired = true;
}
bool EobCoreEngine::updateObjectFlight(EobFlyingObject *fo, int block, int pos) {
uint8 wallFlags = _wllWallFlags[_levelBlockProperties[block].walls[fo->direction ^ 2]];
if (fo->enable == 1) {
if ((wallFlags & 1) || (fo->u2) || ((wallFlags & 2) && (_dscItemShapeMap[_items[fo->item].icon] >= 15))) {
getQueuedItem((Item*)&_levelBlockProperties[fo->curBlock].drawObjects, 0, fo->item);
setItemPosition((Item*)&_levelBlockProperties[block].drawObjects, block, fo->item, pos | 4);
fo->curBlock = block;
fo->curPos = pos;
fo->distance--;
return true;
} else {
_clickedSpecialFlag = 0x10;
specialWallAction(block, fo->direction);
return false;
}
} else {
if (!(wallFlags & 1) && (fo->curBlock != block))
return false;
fo->curBlock = block;
fo->curPos = pos;
if (fo->distance != 255)
fo->distance--;
}
return true;
}
bool EobCoreEngine::updateFlyingObjectHitTest(EobFlyingObject *fo, int block, int pos) {
if (fo->u2 && (fo->curBlock != _currentBlock || fo->attackerId >= 0) && (!blockHasMonsters(block) || fo->attackerId < 0))
return false;
if (fo->enable == 2) {
if (fo->callBackIndex)
return (this->*_spells[fo->callBackIndex].endCallback)(fo);
}
if (blockHasMonsters(block)) {
for (int i = 0; i < 30; i++) {
if (!isMonsterOnPos(&_monsters[i], block, pos, 1))
continue;
if (flyingObjectMonsterHit(fo, i))
return true;
}
} else if (block == _currentBlock) {
return flyingObjectPartyHit(fo);
}
return false;
}
void EobCoreEngine::updateFlyingObject_s3(EobFlyingObject *fo) {
}
void EobCoreEngine::endObjectFlight(EobFlyingObject *fo) {
if (fo->enable == 1) {
_items[fo->item].pos &= 3;
runLevelScript(fo->curBlock, 4);
updateEnvironmentalSfx(18);
}
memset(fo, 0, sizeof(EobFlyingObject));
}
void EobCoreEngine::checkFlyingObjects() {
for (int i = 0; i < 10; i++) {
EobFlyingObject *fo = &_flyingObjects[i];
if (!fo->enable)
continue;
if (updateFlyingObjectHitTest(fo, fo->curBlock, fo->curPos))
endObjectFlight(fo);
}
}
void EobCoreEngine::reloadWeaponSlot(int charIndex, int slotIndex, int itemType, int arrowOrDagger) {
if (arrowOrDagger && _characters[charIndex].inventory[16]) {
_characters[charIndex].inventory[slotIndex] = getQueuedItem(&_characters[charIndex].inventory[16], 0, -1);
} else {
for (int i = 24; i >= 22; i--) {
if (!_characters[charIndex].inventory[i])
continue;
if (_items[_characters[charIndex].inventory[i]].type == itemType && itemType != -1)
continue;
_characters[charIndex].inventory[slotIndex] = _characters[charIndex].inventory[i];
_characters[charIndex].inventory[i] = 0;
return;
}
}
}
} // End of namespace Kyra
#endif // ENABLE_EOB

View File

@ -171,7 +171,7 @@ KyraEngine_HoF::~KyraEngine_HoF() {
delete[] _conversationState[i];
delete[] _conversationState;
for (Common::Array<const TIMOpcode *>::iterator i = _timOpcodes.begin(); i != _timOpcodes.end(); ++i)
for (Common::Array<const TIMOpcode*>::iterator i = _timOpcodes.begin(); i != _timOpcodes.end(); ++i)
delete *i;
_timOpcodes.clear();
}

View File

@ -656,7 +656,7 @@ protected:
int t2_resetChat(const TIM *tim, const uint16 *param);
int t2_playSoundEffect(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode *> _timOpcodes;
Common::Array<const TIMOpcode*> _timOpcodes;
// sound
int _oldTalkFile;

View File

@ -183,7 +183,7 @@ KyraEngine_MR::~KyraEngine_MR() {
delete[] _sceneStrings;
delete[] _talkObjectList;
for (Common::Array<const Opcode *>::iterator i = _opcodesDialog.begin(); i != _opcodesDialog.end(); ++i)
for (Common::Array<const Opcode*>::iterator i = _opcodesDialog.begin(); i != _opcodesDialog.end(); ++i)
delete *i;
_opcodesDialog.clear();

View File

@ -463,7 +463,7 @@ private:
void npcChatSequence(const char *str, int object, int vocHigh, int vocLow);
Common::Array<const Opcode *> _opcodesDialog;
Common::Array<const Opcode*> _opcodesDialog;
int o3d_updateAnim(EMCState *script);
int o3d_delay(EMCState *script);

View File

@ -211,7 +211,7 @@ Common::Error KyraEngine_v1::init() {
}
KyraEngine_v1::~KyraEngine_v1() {
for (Common::Array<const Opcode *>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
delete *i;
_opcodes.clear();
_keyMap.clear();
@ -354,14 +354,14 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)
}
void KyraEngine_v1::setupKeyMap() {
struct KeyMapEntry {
struct KeyCodeMapEntry {
Common::KeyCode kcScummVM;
int16 kcDOS;
int16 kcPC98;
};
#define KC(x) Common::KEYCODE_##x
static const KeyMapEntry keys[] = {
static const KeyCodeMapEntry keys[] = {
{ KC(SPACE), 61, 53 },
{ KC(RETURN), 43, 29 },
{ KC(UP), 96, 68 },
@ -377,13 +377,48 @@ void KyraEngine_v1::setupKeyMap() {
{ KC(KP7), 91, 67 },
{ KC(PAGEUP), 101, 69 },
{ KC(KP9), 101, 69 },
{ KC(END), 93, 0/*unknown*/ },
{ KC(KP1), 93, 0/*unknown*/ },
{ KC(PAGEDOWN), 103, 0/*unknown*/ },
{ KC(KP3), 103, 0/*unknown*/ },
{ KC(F1), 112, 99 },
{ KC(F2), 113, 100 },
{ KC(F3), 114, 101 },
{ KC(F4), 115, 102 },
{ KC(F5), 116, 103 },
{ KC(F6), 117, 104 },
{ KC(a), 31, 31 },
{ KC(b), 50, 50 },
{ KC(c), 48, 48 },
{ KC(d), 33, 33 },
{ KC(e), 19, 19 },
{ KC(f), 34, 34 },
{ KC(i), 24, 24 },
{ KC(k), 38, 38 },
{ KC(m), 52, 52 },
{ KC(n), 51, 51 },
{ KC(o), 25, 25 },
{ KC(p), 26, 26 },
{ KC(r), 20, 20 },
{ KC(s), 32, 32 },
{ KC(w), 18, 18 },
{ KC(y), 22, 22 },
{ KC(z), 46, 46 },
{ KC(1), 2, 0/*unknown*/ },
{ KC(2), 3, 0/*unknown*/ },
{ KC(3), 4, 0/*unknown*/ },
{ KC(4), 5, 0/*unknown*/ },
{ KC(5), 6, 0/*unknown*/ },
{ KC(6), 7, 0/*unknown*/ },
{ KC(7), 8, 0/*unknown*/ },
{ KC(SLASH), 55, 55 },
{ KC(ESCAPE), 110, 1 },
{ KC(MINUS), 12, 0/*unknown*/ },
{ KC(KP_MINUS), 105, 0/*unknown*/ },
{ KC(PLUS), 13, 0/*unknown*/ },
{ KC(KP_PLUS), 106, 0/*unknown*/ },
{ KC(COMMA), 53, 0/*unknown*/ },
{ KC(PERIOD), 54, 0/*unknown*/ }
};
#undef KC

View File

@ -323,7 +323,7 @@ protected:
// opcode
virtual void setupOpcodeTable() = 0;
Common::Array<const Opcode *> _opcodes;
Common::Array<const Opcode*> _opcodes;
int o1_queryGameFlag(EMCState *script);
int o1_setGameFlag(EMCState *script);

View File

@ -252,7 +252,7 @@ protected:
virtual void uninitAnimationShapes(int count, uint8 *filedata) = 0;
// Shapes
typedef Common::HashMap<int, uint8 *> ShapeMap;
typedef Common::HashMap<int, uint8*> ShapeMap;
ShapeMap _gameShapes;
uint8 *getShapePtr(int index) const;

View File

@ -42,10 +42,9 @@ namespace Kyra {
const char *const LoLEngine::kKeymapName = "lol";
LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(system, flags) {
LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : LolEobBaseEngine(system, flags) {
_screen = 0;
_gui = 0;
_txt = 0;
_tim = 0;
_lang = 0;
@ -97,15 +96,11 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_inventory, 0, sizeof(_inventory));
memset(_charStatusFlags, 0, sizeof(_charStatusFlags));
_inventoryCurItem = 0;
_currentControlMode = 0;
_specialSceneFlag = 0;
_lastCharInventory = -1;
_emcLastItem = -1;
_itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = _healShapes = _healiShapes = 0;
_levelShpList = _levelDatList = 0;
_monsterShapes = _monsterPalettes = 0;
_monsterShapesEx = 0;
_gameShapeMap = 0;
memset(_monsterAnimType, 0, 3);
_healOverlay = 0;
@ -116,10 +111,8 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_charSelection = -1;
_characters = 0;
_spellProperties = 0;
_updateFlags = 0;
_selectedSpell = 0;
_updateCharNum = _updatePortraitSpeechAnimDuration = _portraitSpeechAnimMode = _resetPortraitAfterSpeechAnim = _textColorFlag = _needSceneRestore = 0;
_fadeText = false;
_updateCharNum = _portraitSpeechAnimMode = _textColorFlag = 0;
_palUpdateTimer = _updatePortraitNext = 0;
_lampStatusTimer = 0xffffffff;
@ -128,66 +121,42 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_lastButtonShape = 0;
_buttonPressTimer = 0;
_selectedCharacter = 0;
_suspendScript = _sceneUpdateRequired = false;
_suspendScript = false;
_scriptDirection = 0;
_currentDirection = 0;
_currentBlock = 0;
_compassDirection = _compassDirectionIndex = -1;
_compassDirectionIndex = -1;
_compassStep = 0;
memset(_visibleBlockIndex, 0, sizeof(_visibleBlockIndex));
_smoothScrollModeNormal = 1;
_wllVmpMap = _specialWallTypes = _wllBuffer4 = _wllWallFlags = 0;
_wllShapeMap = 0;
_lvlShapeTop = _lvlShapeBottom = _lvlShapeLeftRight = 0;
_levelBlockProperties = 0;
_wllAutomapData = 0;
_sceneXoffset = 112;
_sceneShpDim = 13;
_monsters = 0;
_monsterProperties = 0;
_lvlBlockIndex = _lvlShapeIndex = 0;
_lvlShapeIndex = 0;
_partyAwake = true;
_vcnBlocks = 0;
_vcnShift = 0;
_vcnExpTable = 0;
_vmpPtr = 0;
_vcfBlocks = 0;
_transparencyTable2 = 0;
_transparencyTable1 = 0;
_levelShapeProperties = 0;
_levelShapes = 0;
_specialGuiShape = 0;
_specialGuiShapeX = _specialGuiShapeY = _specialGuiShapeMirrorFlag = 0;
_blockDrawingBuffer = 0;
_sceneWindowBuffer = 0;
memset(_doorShapes, 0, sizeof(_doorShapes));
memset(_characterFaceShapes, 0, sizeof(_characterFaceShapes));
_lampEffect = _brightness = _lampOilStatus = 0;
_lampStatusSuspended = false;
_blockBrightness = 0;
_tempBuffer5120 = 0;
_flyingObjects = 0;
_monsters = 0;
_lastMouseRegion = 0;
_objectLastDirection = _monsterStepCounter = _monsterStepMode = 0;
_objectLastDirection = 0;
_monsterCurBlock = 0;
_seqWindowX1 = _seqWindowY1 = _seqWindowX2 = _seqWindowY2 = _seqTrigger = 0;
_spsWindowX = _spsWindowY = _spsWindowW = _spsWindowH = 0;
_dscUnk1 = 0;
_dscShapeIndex = 0;
_dscWalls = 0;
_dscOvlMap = 0;
_dscShapeScaleW = 0;
_dscShapeScaleH = 0;
_dscShapeX = 0;
_dscShapeScaleH = 0;
_dscShapeY = 0;
_dscTileIndex = 0;
_dscUnk2 = 0;
_dscDoorShpIndex = 0;
_dscDim1 = 0;
_dscDim2 = 0;
_dscBlockMap = _dscDoor1 = _dscShapeOvlIndex = 0;
_dscBlockIndex = 0;
_dscDimMap = 0;
_dscShapeOvlIndex = 0;
_dscDoorMonsterX = _dscDoorMonsterY = 0;
_dscDoor4 = 0;
@ -198,29 +167,24 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_curMusicTheme = -1;
_curMusicFileExt = 0;
_curMusicFileIndex = -1;
_environmentSfx = _environmentSfxVol = _envSfxDistThreshold = 0;
_envSfxUseQueue = false;
_envSfxNumTracksInQueue = 0;
memset(_envSfxQueuedTracks, 0, sizeof(_envSfxQueuedTracks));
memset(_envSfxQueuedBlocks, 0, sizeof(_envSfxQueuedBlocks));
_sceneDrawVarDown = _sceneDrawVarRight = _sceneDrawVarLeft = _wllProcessFlag = 0;
_partyPosX = _partyPosY = 0;
_shpDmX = _shpDmY = _dmScaleW = _dmScaleH = 0;
_floatingCursorControl = _currentFloatingCursor = 0;
memset(_activeTim, 0, sizeof(_activeTim));
memset(_openDoorState, 0, sizeof(_openDoorState));
memset(&_activeSpell, 0, sizeof(_activeSpell));
_activeVoiceFileTotalTime = 0;
_pageBuffer1 = _pageBuffer2 = 0;
memset(_charStatsTemp, 0, sizeof(_charStatsTemp));
_compassBroken = _drainMagic = 0;
_dialogueField = false;
_buttonData = 0;
_activeButtons = 0;
@ -228,8 +192,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_preserveEvents = false;
_buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0;
memset(_lvlTempData, 0, sizeof(_lvlTempData));
_mapOverlay = 0;
_automapShapes = 0;
_defaultLegendData = 0;
@ -250,6 +212,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
LoLEngine::~LoLEngine() {
setupPrologueData(false);
releaseTempData();
#ifdef ENABLE_KEYMAPPER
_eventMan->getKeymapper()->cleanupGameKeymaps();
@ -264,8 +227,6 @@ LoLEngine::~LoLEngine() {
_gui = 0;
delete _tim;
_tim = 0;
delete _txt;
_txt = 0;
delete[] _itemsInPlay;
delete[] _itemProperties;
@ -322,64 +283,47 @@ LoLEngine::~LoLEngine() {
delete[] _healiShapes;
}
for (int i = 0; i < 3; i++)
releaseMonsterShapes(i);
if (_monsterDecorationShapes) {
for (int i = 0; i < 3; i++)
releaseMonsterShapes(i);
delete[] _monsterShapes;
delete[] _monsterPalettes;
delete[] _monsterShapesEx;
delete[] _monsterShapes;
_monsterShapes = 0;
delete[] _monsterPalettes;
_monsterPalettes = 0;
delete[] _monsterDecorationShapes;
_monsterDecorationShapes = 0;
}
for (int i = 0; i < 6; i++) {
delete[] _doorShapes[i];
_doorShapes[i] = 0;
}
delete[] _automapShapes;
for (Common::Array<const TIMOpcode *>::iterator i = _timIntroOpcodes.begin(); i != _timIntroOpcodes.end(); ++i)
for (Common::Array<const TIMOpcode*>::iterator i = _timIntroOpcodes.begin(); i != _timIntroOpcodes.end(); ++i)
delete *i;
_timIntroOpcodes.clear();
for (Common::Array<const TIMOpcode *>::iterator i = _timOutroOpcodes.begin(); i != _timOutroOpcodes.end(); ++i)
for (Common::Array<const TIMOpcode*>::iterator i = _timOutroOpcodes.begin(); i != _timOutroOpcodes.end(); ++i)
delete *i;
_timOutroOpcodes.clear();
for (Common::Array<const TIMOpcode *>::iterator i = _timIngameOpcodes.begin(); i != _timIngameOpcodes.end(); ++i)
for (Common::Array<const TIMOpcode*>::iterator i = _timIngameOpcodes.begin(); i != _timIngameOpcodes.end(); ++i)
delete *i;
_timIngameOpcodes.clear();
delete[] _wllVmpMap;
delete[] _wllShapeMap;
delete[] _specialWallTypes;
delete[] _wllBuffer4;
delete[] _wllWallFlags;
delete[] _lvlShapeTop;
delete[] _lvlShapeBottom;
delete[] _lvlShapeLeftRight;
delete[] _wllAutomapData;
delete[] _tempBuffer5120;
delete[] _flyingObjects;
delete[] _monsters;
delete[] _levelBlockProperties;
delete[] _monsterProperties;
delete[] _levelFileData;
delete[] _vcnExpTable;
delete[] _vcnBlocks;
delete[] _vcnShift;
delete[] _vmpPtr;
delete[] _vcfBlocks;
delete[] _transparencyTable2;
delete[] _transparencyTable1;
delete[] _levelShapeProperties;
delete[] _blockDrawingBuffer;
delete[] _sceneWindowBuffer;
delete[] _lightningProps;
if (_levelShapes) {
for (int i = 0; i < 400; i++)
delete[] _levelShapes[i];
delete[] _levelShapes;
}
for (int i = 0; i < 2; i++)
delete[] _doorShapes[i];
delete _lvlShpFileHandle;
if (_ingameSoundList) {
@ -388,16 +332,6 @@ LoLEngine::~LoLEngine() {
delete[] _ingameSoundList;
}
for (int i = 0; i < 29; i++) {
if (_lvlTempData[i]) {
delete[] _lvlTempData[i]->wallsXorData;
delete[] _lvlTempData[i]->flags;
delete[] _lvlTempData[i]->monsters;
delete[] _lvlTempData[i]->flyingObjects;
delete _lvlTempData[i];
}
}
for (int i = 0; i < 3; i++) {
for (int ii = 0; ii < 40; ii++)
delete[] _characterFaceShapes[ii][i];
@ -409,7 +343,7 @@ LoLEngine::~LoLEngine() {
delete[] _mapCursorOverlay;
delete[] _mapOverlay;
for (Common::Array<const SpellProc *>::iterator i = _spellProcs.begin(); i != _spellProcs.end(); ++i)
for (Common::Array<const SpellProc*>::iterator i = _spellProcs.begin(); i != _spellProcs.end(); ++i)
delete *i;
_spellProcs.clear();
@ -440,13 +374,18 @@ Common::Error LoLEngine::init() {
KyraEngine_v1::init();
initStaticResource();
_envSfxDistThreshold = _sound->getSfxType() == Sound::kAdLib ? 15 : 3;
_gui = new GUI_LoL(this);
assert(_gui);
_gui->initStaticData();
_txt = new TextDisplayer_LoL(this, _screen);
_dialogueButtonLabelCol1 = 144;
_dialogueButtonLabelCol2 = 254;
_dialogueButtonW = 74;
_dialogueButtonH = 9;
_bkgColor_1 = -1;
_color1_1 = 136;
_color2_1 = 251;
_screen->setAnimBlockPtr(10000);
_screen->setScreenDim(0);
@ -465,41 +404,15 @@ Common::Error LoLEngine::init() {
if (!_sound->init())
error("Couldn't init sound");
_wllVmpMap = new uint8[80];
memset(_wllVmpMap, 0, 80);
_wllShapeMap = new int8[80];
memset(_wllShapeMap, 0, 80);
_specialWallTypes = new uint8[80];
memset(_specialWallTypes, 0, 80);
_wllBuffer4 = new uint8[80];
memset(_wllBuffer4, 0, 80);
_wllWallFlags = new uint8[80];
memset(_wllWallFlags, 0, 80);
_lvlShapeTop = new int16[18];
memset(_lvlShapeTop, 0, 18 * sizeof(int16));
_lvlShapeBottom = new int16[18];
memset(_lvlShapeBottom, 0, 18 * sizeof(int16));
_lvlShapeLeftRight = new int16[36];
memset(_lvlShapeLeftRight, 0, 36 * sizeof(int16));
_levelShapeProperties = new LevelShapeProperty[100];
memset(_levelShapeProperties, 0, 100 * sizeof(LevelShapeProperty));
_levelShapes = new uint8 *[400];
memset(_levelShapes, 0, 400 * sizeof(uint8 *));
_blockDrawingBuffer = new uint16[1320];
memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16));
_sceneWindowBuffer = new uint8[21120];
memset(_sceneWindowBuffer, 0, 21120);
LolEobBaseEngine::init();
_wllAutomapData = new uint8[80];
memset(_wllAutomapData, 0, 80);
_levelBlockProperties = new LevelBlockProperty[1025];
memset(_levelBlockProperties, 0, 1025 * sizeof(LevelBlockProperty));
_monsters = new MonsterInPlay[30];
memset(_monsters, 0, 30 * sizeof(MonsterInPlay));
_monsterProperties = new MonsterProperty[5];
memset(_monsterProperties, 0, 5 * sizeof(MonsterProperty));
_vcnExpTable = new uint8[128];
for (int i = 0; i < 128; i++)
_vcnExpTable[i] = i & 0x0f;
_monsters = new LolMonsterInPlay[30];
memset(_monsters, 0, 30 * sizeof(LolMonsterInPlay));
_monsterProperties = new LolMonsterProperty[5];
memset(_monsterProperties, 0, 5 * sizeof(LolMonsterProperty));
_tempBuffer5120 = new uint8[5120];
memset(_tempBuffer5120, 0, 5120);
@ -509,25 +422,26 @@ Common::Error LoLEngine::init() {
memset(_globalScriptVars, 0, sizeof(_globalScriptVars));
_levelFileData = 0;
_lvlShpFileHandle = 0;
_sceneDrawPage1 = 2;
_sceneDrawPage2 = 6;
_monsterShapes = new uint8 *[48];
memset(_monsterShapes, 0, 48 * sizeof(uint8 *));
_monsterPalettes = new uint8 *[48];
memset(_monsterPalettes, 0, 48 * sizeof(uint8 *));
_clickedShapeXOffs = 136;
_clickedShapeYOffs = 8;
_clickedSpecialFlag = 0x40;
_monsterShapesEx = new uint8 *[576];
memset(_monsterShapesEx, 0, 576 * sizeof(uint8 *));
_monsterShapes = new uint8*[48];
memset(_monsterShapes, 0, 48 * sizeof(uint8*));
_monsterPalettes = new uint8*[48];
memset(_monsterPalettes, 0, 48 * sizeof(uint8*));
_monsterDecorationShapes = new uint8*[576];
memset(_monsterDecorationShapes, 0, 576 * sizeof(uint8*));
memset(&_scriptData, 0, sizeof(EMCData));
_hasTempDataFlags = 0;
_activeMagicMenu = -1;
_automapShapes = new const uint8 *[109];
_automapShapes = new const uint8*[109];
_mapOverlay = new uint8[256];
memset(_availableSpells, -1, 8);
@ -687,7 +601,7 @@ void LoLEngine::loadItemIconShapes() {
_screen->loadBitmap("ITEMICN.SHP", 3, 3, 0);
const uint8 *shp = _screen->getCPagePtr(3);
_numItemIconShapes = READ_LE_UINT16(shp);
_itemIconShapes = new uint8 *[_numItemIconShapes];
_itemIconShapes = new uint8*[_numItemIconShapes];
for (int i = 0; i < _numItemIconShapes; i++)
_itemIconShapes[i] = _screen->makeShapeCopy(shp, i);
@ -697,7 +611,7 @@ void LoLEngine::loadItemIconShapes() {
_screen->loadBitmap("GAMESHP.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numGameShapes = READ_LE_UINT16(shp);
_gameShapes = new uint8 *[_numGameShapes];
_gameShapes = new uint8*[_numGameShapes];
for (int i = 0; i < _numGameShapes; i++)
_gameShapes[i] = _screen->makeShapeCopy(shp, i);
}
@ -717,12 +631,6 @@ void LoLEngine::setMouseCursorToItemInHand() {
_screen->setMouseCursor(o, o, getItemIconShapePtr(_itemInHand));
}
bool LoLEngine::posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2) {
if (mouseX < x1 || mouseX > x2 || mouseY < y1 || mouseY > y2)
return false;
return true;
}
void LoLEngine::checkFloatingPointerRegions() {
if (!_floatingCursorsEnabled)
return;
@ -877,42 +785,42 @@ void LoLEngine::startup() {
_screen->loadBitmap("ITEMSHP.SHP", 3, 3, 0);
const uint8 *shp = _screen->getCPagePtr(3);
_numItemShapes = READ_LE_UINT16(shp);
_itemShapes = new uint8 *[_numItemShapes];
_itemShapes = new uint8*[_numItemShapes];
for (int i = 0; i < _numItemShapes; i++)
_itemShapes[i] = _screen->makeShapeCopy(shp, i);
_screen->loadBitmap("THROWN.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numThrownShapes = READ_LE_UINT16(shp);
_thrownShapes = new uint8 *[_numThrownShapes];
_thrownShapes = new uint8*[_numThrownShapes];
for (int i = 0; i < _numThrownShapes; i++)
_thrownShapes[i] = _screen->makeShapeCopy(shp, i);
_screen->loadBitmap("ICE.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numEffectShapes = READ_LE_UINT16(shp);
_effectShapes = new uint8 *[_numEffectShapes];
_effectShapes = new uint8*[_numEffectShapes];
for (int i = 0; i < _numEffectShapes; i++)
_effectShapes[i] = _screen->makeShapeCopy(shp, i);
_screen->loadBitmap("FIREBALL.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numFireballShapes = READ_LE_UINT16(shp);
_fireballShapes = new uint8 *[_numFireballShapes];
_fireballShapes = new uint8*[_numFireballShapes];
for (int i = 0; i < _numFireballShapes; i++)
_fireballShapes[i] = _screen->makeShapeCopy(shp, i);
_screen->loadBitmap("HEAL.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numHealShapes = READ_LE_UINT16(shp);
_healShapes = new uint8 *[_numHealShapes];
_healShapes = new uint8*[_numHealShapes];
for (int i = 0; i < _numHealShapes; i++)
_healShapes[i] = _screen->makeShapeCopy(shp, i);
_screen->loadBitmap("HEALI.SHP", 3, 3, 0);
shp = _screen->getCPagePtr(3);
_numHealiShapes = READ_LE_UINT16(shp);
_healiShapes = new uint8 *[_numHealiShapes];
_healiShapes = new uint8*[_numHealiShapes];
for (int i = 0; i < _numHealiShapes; i++)
_healiShapes[i] = _screen->makeShapeCopy(shp, i);
@ -969,10 +877,9 @@ void LoLEngine::runLoop() {
enableSysTimer(2);
bool _runFlag = true;
_flagsTable[73] |= 0x08;
while (!shouldQuit() && _runFlag) {
while (!shouldQuit()) {
if (_gameToLoad != -1) {
// FIXME: Instead of throwing away the error returned by
// loadGameState, we should use it / augment it.
@ -1784,44 +1691,6 @@ void LoLEngine::fadeText() {
_fadeText = false;
}
void LoLEngine::transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage) {
uint16 *p1 = (uint16 *)_tempBuffer5120;
uint16 *p2 = (uint16 *)(_tempBuffer5120 + 640);
for (int i = 0; i < w; i++)
p1[i] = i;
for (int i = 0; i < h; i++)
p2[i] = i;
for (int i = 0; i < w; i++)
SWAP(p1[_rnd.getRandomNumberRng(0, w - 1)], p1[i]);
for (int i = 0; i < h; i++)
SWAP(p2[_rnd.getRandomNumberRng(0, h - 1)], p2[i]);
for (int i = 0; i < h; i++) {
int i2 = i;
for (int ii = 0; ii < w; ii++) {
int dx1 = x1 + p1[ii];
int dy1 = y1 + p2[i2];
int dx2 = x2 + p1[ii];
int dy2 = y2 + p2[i2];
if (++i2 == h)
i2 = 0;
_screen->setPagePixel(dstPage, dx2, dy2, _screen->getPagePixel(srcPage, dx1, dy1));
}
if (!dstPage && (i & 5) == 5) {
updateInput();
_screen->updateScreen();
}
}
}
void LoLEngine::setPaletteBrightness(const Palette &srcPal, int brightness, int modifier) {
generateBrightnessPalette(srcPal, _screen->getPalette(1), brightness, modifier);
_screen->fadePalette(_screen->getPalette(1), 5, 0);
@ -2040,7 +1909,46 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int restorePortrait
return 1;
}
void LoLEngine::giveItemToMonster(MonsterInPlay *monster, Item item) {
void LoLEngine::setupDialogueButtons(int numStr, const char *s1, const char *s2, const char *s3) {
screen()->setScreenDim(5);
if (numStr == 1 && speechEnabled()) {
_dialogueNumButtons = 0;
_dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0;
} else {
_dialogueNumButtons = numStr;
_dialogueButtonString[0] = s1;
_dialogueButtonString[1] = s2;
_dialogueButtonString[2] = s3;
_dialogueHighlightedButton = 0;
const ScreenDim *d = screen()->getScreenDim(5);
static uint16 posX[3];
static uint8 posY[3];
memset(posY, d->sy + d->h - 9, 3);
_dialogueButtonPosX = posX;
_dialogueButtonPosY = posY;
if (numStr == 1) {
posX[0] = posX[1] = posX[2] = d->sx + d->w - (_dialogueButtonW + 3);
} else {
int xOffs = d->w / numStr;
posX[0] = d->sx + (xOffs >> 1) - 37;
posX[1] = posX[0] + xOffs;
posX[2] = posX[1] + xOffs;
}
drawDialogueButtons();
}
if (!shouldQuit())
removeInputTop();
}
void LoLEngine::giveItemToMonster(LolMonsterInPlay *monster, Item item) {
uint16 *c = &monster->assignedItems;
while (*c)
c = &_itemsInPlay[*c].nextAssignedObject;
@ -2049,7 +1957,7 @@ void LoLEngine::giveItemToMonster(MonsterInPlay *monster, Item item) {
}
const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) {
return (id & 0x8000) ? (const uint16 *)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers;
return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers;
}
uint16 *LoLEngine::getCharacterOrMonsterItemsMight(int id) {
@ -2073,21 +1981,6 @@ void LoLEngine::delay(uint32 millis, bool doUpdate, bool) {
}
}
int LoLEngine::rollDice(int times, int pips) {
if (times <= 0 || pips <= 0)
return 0;
int res = 0;
while (times--)
res += _rnd.getRandomNumberRng(1, pips);
return res;
}
void LoLEngine::updateEnvironmentalSfx(int soundId) {
snd_processEnvironmentalSoundEffect(soundId, _currentBlock);
}
// spells
int LoLEngine::castSpell(int charNum, int spellType, int spellLevel) {
@ -2502,7 +2395,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) {
int might = rollDice(iceDamageMin[spellLevel], iceDamageMax[spellLevel]) + iceDamageAdd[spellLevel];
int dmg = calcInflictableDamagePerItem(charNum, 0, might, 3, 2);
MonsterInPlay *m = &_monsters[o & 0x7fff];
LolMonsterInPlay *m = &_monsters[o & 0x7fff];
if (m->hitPoints <= dmg) {
increaseExperience(charNum, 2, m->hitPoints);
o = m->nextAssignedObject;
@ -2581,7 +2474,7 @@ int LoLEngine::processMagicFireball(int charNum, int spellLevel) {
while (o & 0x8000) {
static const uint8 fireballDamage[] = { 20, 40, 80, 100 };
int dmg = calcInflictableDamagePerItem(charNum, o, fireballDamage[spellLevel], 4, 1);
MonsterInPlay *m = &_monsters[o & 0x7fff];
LolMonsterInPlay *m = &_monsters[o & 0x7fff];
o = m->nextAssignedObject;
_envSfxUseQueue = true;
inflictDamage(m->id | 0x8000, dmg, charNum, 2, 4);
@ -2746,7 +2639,7 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) {
uint16 o = _levelBlockProperties[b1].assignedObjects;
while (o & 0x8000) {
uint16 o2 = o;
MonsterInPlay *m = &_monsters[o & 0x7fff];
LolMonsterInPlay *m = &_monsters[o & 0x7fff];
o = findObject(o)->nextAssignedObject;
int nX = 0;
int nY = 0;
@ -3015,7 +2908,7 @@ int LoLEngine::processMagicVaelansCube() {
uint16 o = _levelBlockProperties[bl].assignedObjects;
while (o & 0x8000) {
MonsterInPlay *m = &_monsters[o & 0x7fff];
LolMonsterInPlay *m = &_monsters[o & 0x7fff];
if (m->properties->flags & 0x1000) {
inflictDamage(o, 100, 0xffff, 0, 0x80);
v = 1;
@ -3495,7 +3388,7 @@ int LoLEngine::calcInflictableDamage(int16 attacker, int16 target, int hitType)
}
int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int skill, int flags) {
MonsterInPlay *m = 0;
LolMonsterInPlay *m = 0;
LoLCharacter *c = 0;
if (target & 0x8000) {
@ -3712,7 +3605,7 @@ void LoLEngine::checkForPartyDeath() {
}
}
void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) {
void LoLEngine::applyMonsterAttackSkill(LolMonsterInPlay *monster, int16 target, int16 damage) {
if (rollDice(1, 100) > monster->properties->attackSkillChance)
return;
@ -3782,7 +3675,7 @@ void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, in
}
}
void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int flags, int skill, int damage) {
void LoLEngine::applyMonsterDefenseSkill(LolMonsterInPlay *monster, int16 attacker, int flags, int skill, int damage) {
if (rollDice(1, 100) > monster->properties->defenseSkillChance)
return;
@ -4041,7 +3934,7 @@ uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(uint16 block, int charN
int o = _levelBlockProperties[block].assignedObjects;
while (o & 0x8000) {
MonsterInPlay *m = &_monsters[o & 0x7fff];
LolMonsterInPlay *m = &_monsters[o & 0x7fff];
if (m->mode >= 13) {
o = m->nextAssignedObject;
continue;
@ -4107,7 +4000,7 @@ void LoLEngine::displayAutomap() {
_currentMapLevel = _currentLevel;
uint8 *tmpWll = new uint8[80];
memcpy(tmpWll, _wllBuffer4, 80);
memcpy(tmpWll, _wllAutomapData, 80);
_screen->loadBitmap("parch.cps", 2, 2, &_screen->getPalette(3));
_screen->loadBitmap("autobut.shp", 3, 5, 0);
@ -4188,7 +4081,7 @@ void LoLEngine::displayAutomap() {
_screen->fadeToBlack(10);
loadLevelWallData(_currentLevel, false);
memcpy(_wllBuffer4, tmpWll, 80);
memcpy(_wllAutomapData, tmpWll, 80);
delete[] tmpWll;
restoreBlockTempData(_currentLevel);
addLevelItems();
@ -4229,7 +4122,7 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff
uint16 b = block + blockPosTable[6 + xOffs];
if (fx != -1) {
if (_wllBuffer4[_levelBlockProperties[b].walls[fx]] & 0xc0)
if (_wllAutomapData[_levelBlockProperties[b].walls[fx]] & 0xc0)
return false;
}
@ -4237,13 +4130,13 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff
b = block + blockPosTable[9 + yOffs];
if (fy != -1) {
if (_wllBuffer4[_levelBlockProperties[b].walls[fy]] & 0xc0)
if (_wllAutomapData[_levelBlockProperties[b].walls[fy]] & 0xc0)
return false;
}
b = block + blockPosTable[6 + xOffs] + blockPosTable[9 + yOffs];
if ((fx != -1) && (fy != -1) && (_wllBuffer4[_levelBlockProperties[b].walls[fx]] & 0xc0) && (_wllBuffer4[_levelBlockProperties[b].walls[fy]] & 0xc0))
if ((fx != -1) && (fy != -1) && (_wllAutomapData[_levelBlockProperties[b].walls[fx]] & 0xc0) && (_wllAutomapData[_levelBlockProperties[b].walls[fy]] & 0xc0))
return false;
_levelBlockProperties[b].flags |= 7;
@ -4252,7 +4145,7 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff
}
void LoLEngine::loadMapLegendData(int level) {
uint16 *legendData = (uint16 *)_tempBuffer5120;
uint16 *legendData= (uint16*)_tempBuffer5120;
for (int i = 0; i < 32; i++) {
legendData[i * 6] = 0xffff;
legendData[i * 6 + 5] = 0xffff;
@ -4306,7 +4199,7 @@ void LoLEngine::drawMapPage(int pageNum) {
for (; bl < 1024; bl++) {
uint8 *w = _levelBlockProperties[bl].walls;
if ((_levelBlockProperties[bl].flags & 7) == 7 && (!(_wllBuffer4[w[0]] & 0xc0)) && (!(_wllBuffer4[w[2]] & 0xc0)) && (!(_wllBuffer4[w[1]] & 0xc0))&& (!(_wllBuffer4[w[3]] & 0xc0))) {
if ((_levelBlockProperties[bl].flags & 7) == 7 && (!(_wllAutomapData[w[0]] & 0xc0)) && (!(_wllAutomapData[w[2]] & 0xc0)) && (!(_wllAutomapData[w[1]] & 0xc0))&& (!(_wllAutomapData[w[3]] & 0xc0))) {
uint16 b0 = calcNewBlockPosition(bl, 0);
uint16 b2 = calcNewBlockPosition(bl, 2);
uint16 b1 = calcNewBlockPosition(bl, 1);
@ -4323,25 +4216,25 @@ void LoLEngine::drawMapPage(int pageNum) {
// draw north wall
drawMapBlockWall(b3, w31, sx, sy, 3);
drawMapShape(w31, sx, sy, 3);
if (_wllBuffer4[w31] & 0xc0)
if (_wllAutomapData[w31] & 0xc0)
_screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 1, 6, 0, _mapOverlay);
// draw west wall
drawMapBlockWall(b1, w13, sx, sy, 1);
drawMapShape(w13, sx, sy, 1);
if (_wllBuffer4[w13] & 0xc0)
if (_wllAutomapData[w13] & 0xc0)
_screen->copyBlockAndApplyOverlay(_screen->_curPage, sx + 6, sy, _screen->_curPage, sx + 6, sy, 1, 6, 0, _mapOverlay);
// draw east wall
drawMapBlockWall(b0, w02, sx, sy, 0);
drawMapShape(w02, sx, sy, 0);
if (_wllBuffer4[w02] & 0xc0)
if (_wllAutomapData[w02] & 0xc0)
_screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 1, 0, _mapOverlay);
//draw south wall
drawMapBlockWall(b2, w20, sx, sy, 2);
drawMapShape(w20, sx, sy, 2);
if (_wllBuffer4[w20] & 0xc0)
if (_wllAutomapData[w20] & 0xc0)
_screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy + 5, _screen->_curPage, sx, sy + 5, 7, 1, 0, _mapOverlay);
}
@ -4362,7 +4255,7 @@ void LoLEngine::drawMapPage(int pageNum) {
sx = mapGetStartPosX();
sy = mapGetStartPosY();
uint16 *legendData = (uint16 *)_tempBuffer5120;
uint16 *legendData = (uint16*)_tempBuffer5120;
uint8 yOffset = _flags.use16ColorMode ? 4 : 0;
for (int ii = 0; ii < 32; ii++) {
@ -4508,7 +4401,7 @@ void LoLEngine::redrawMapCursor() {
}
void LoLEngine::drawMapBlockWall(uint16 block, uint8 wall, int x, int y, int direction) {
if (((1 << direction) & _levelBlockProperties[block].flags) || ((_wllBuffer4[wall] & 0x1f) != 13))
if (((1 << direction) & _levelBlockProperties[block].flags) || ((_wllAutomapData[wall] & 0x1f) != 13))
return;
int cp = _screen->_curPage;
@ -4518,7 +4411,7 @@ void LoLEngine::drawMapBlockWall(uint16 block, uint8 wall, int x, int y, int dir
}
void LoLEngine::drawMapShape(uint8 wall, int x, int y, int direction) {
int l = _wllBuffer4[wall] & 0x1f;
int l = _wllAutomapData[wall] & 0x1f;
if (l == 0x1f)
return;
@ -4611,48 +4504,7 @@ void LoLEngine::printMapExitButtonText() {
_screen->setCurPage(cp);
}
void LoLEngine::generateTempData() {
int l = _currentLevel - 1;
if (_lvlTempData[l]) {
delete[] _lvlTempData[l]->wallsXorData;
delete[] _lvlTempData[l]->flags;
delete[] _lvlTempData[l]->monsters;
delete[] _lvlTempData[l]->flyingObjects;
delete _lvlTempData[l];
}
_lvlTempData[l] = new LevelTempData;
_lvlTempData[l]->wallsXorData = new uint8[4096];
_lvlTempData[l]->flags = new uint8[1024];
_lvlTempData[l]->monsters = new MonsterInPlay[30];
_lvlTempData[l]->flyingObjects = new FlyingObject[8];
Common::String filename = Common::String::format("LEVEL%d.CMZ", _currentLevel);
_screen->loadBitmap(filename.c_str(), 15, 15, 0);
const uint8 *p = _screen->getCPagePtr(14);
uint16 len = READ_LE_UINT16(p + 4);
p += 6;
memset(_lvlTempData[l]->wallsXorData, 0, 4096);
memset(_lvlTempData[l]->flags, 0, 1024);
uint8 *d = _lvlTempData[l]->wallsXorData;
uint8 *df = _lvlTempData[l]->flags;
for (int i = 0; i < 1024; i++) {
for (int ii = 0; ii < 4; ii++)
*d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
*df++ = _levelBlockProperties[i].flags;
}
memcpy(_lvlTempData[l]->monsters, _monsters, sizeof(MonsterInPlay) * 30);
memcpy(_lvlTempData[l]->flyingObjects, _flyingObjects, sizeof(FlyingObject) * 8);
_lvlTempData[l]->monsterDifficulty =_monsterDifficulty;
_hasTempDataFlags |= (1 << l);
}
} // End of namespace Kyra

View File

@ -25,7 +25,7 @@
#ifndef KYRA_LOL_H
#define KYRA_LOL_H
#include "kyra/kyra_v1.h"
#include "kyra/loleobbase.h"
#include "kyra/script_tim.h"
#include "kyra/script.h"
#include "kyra/gui_lol.h"
@ -86,15 +86,7 @@ struct SpellProperty {
uint16 flags;
};
struct LevelBlockProperty {
uint8 walls[4];
uint16 assignedObjects;
uint16 drawObjects;
uint8 direction;
uint8 flags;
};
struct MonsterProperty {
struct LolMonsterProperty {
uint8 shapeIndex;
uint8 maxWidth;
uint16 fightingStats[9];
@ -116,7 +108,7 @@ struct MonsterProperty {
uint8 sounds[3];
};
struct MonsterInPlay {
struct LolMonsterInPlay {
uint16 nextAssignedObject;
uint16 nextDrawObject;
uint8 flyingHeight;
@ -142,7 +134,7 @@ struct MonsterInPlay {
int16 hitPoints;
uint8 speedTick;
uint8 type;
MonsterProperty *properties;
LolMonsterProperty *properties;
uint8 numDistAttacks;
uint8 curDistWeapon;
int8 distAttackTick;
@ -179,15 +171,6 @@ struct ItemProperty {
uint8 unkD;
};
struct LevelShapeProperty {
uint16 shapeIndex[10];
uint8 scaleFlag[10];
int16 shapeX[10];
int16 shapeY[10];
int8 next;
uint8 flags;
};
struct CompassDef {
uint8 shapeIndex;
int8 x;
@ -195,7 +178,7 @@ struct CompassDef {
uint8 flags;
};
struct ButtonDef {
struct LoLButtonDef {
uint16 buttonflags;
uint16 keyCode;
uint16 keyCode2;
@ -207,12 +190,6 @@ struct ButtonDef {
uint16 screenDim;
};
struct OpenDoorState {
uint16 block;
int8 wall;
int8 state;
};
struct ActiveSpell {
uint8 spell;
const SpellProperty *p;
@ -245,14 +222,6 @@ struct FlyingObjectShape {
uint8 flipFlags;
};
struct LevelTempData {
uint8 *wallsXorData;
uint8 *flags;
MonsterInPlay *monsters;
FlyingObject *flyingObjects;
uint8 monsterDifficulty;
};
struct MapLegendData {
uint8 shapeIndex;
bool enable;
@ -296,7 +265,7 @@ struct MistOfDoomAnimData {
uint8 sound;
};
class LoLEngine : public KyraEngine_v1 {
class LoLEngine : public LolEobBaseEngine {
friend class GUI_LoL;
friend class TextDisplayer_LoL;
friend class TIMInterpreter_LoL;
@ -305,7 +274,7 @@ friend class Debugger_LoL;
friend class HistoryPlayer;
public:
LoLEngine(OSystem *system, const GameFlags &flags);
~LoLEngine();
virtual ~LoLEngine();
virtual void initKeymap();
@ -348,13 +317,11 @@ private:
// main loop
void runLoop();
void update();
void updateEnvironmentalSfx(int soundId);
// mouse
void setMouseCursorToIcon(int icon);
void setMouseCursorToItemInHand();
uint8 *getItemIconShapePtr(int index);
bool posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2);
void checkFloatingPointerRegions();
int _floatingCursorControl;
@ -443,11 +410,7 @@ private:
// timers
void setupTimers();
void enableTimer(int id);
void enableSysTimer(int sysTimer);
void disableSysTimer(int sysTimer);
void timerProcessDoors(int timerNum);
void timerProcessMonsters(int timerNum);
void timerSpecialCharacterUpdate(int timerNum);
void timerProcessFlyingObjects(int timerNum);
@ -457,6 +420,9 @@ private:
void timerUpdateLampState(int timerNum);
void timerFadeMessageText(int timerNum);
uint8 getClock2Timer(int index) { return index < _numClock2Timers ? _clock2Timers[index] : 0; }
uint8 getNumClock2Timers() { return _numClock2Timers; }
static const uint8 _clock2Timers[];
static const uint8 _numClock2Timers;
@ -470,7 +436,7 @@ private:
int snd_updateCharacterSpeech();
void snd_stopSpeech(bool setFlag);
void snd_playSoundEffect(int track, int volume);
void snd_processEnvironmentalSoundEffect(int soundId, int block);
bool snd_processEnvironmentalSoundEffect(int soundId, int block);
void snd_queueEnvironmentalSoundEffect(int soundId, int block);
void snd_playQueuedEffects();
void snd_loadSoundFile(int track);
@ -479,21 +445,17 @@ private:
int _lastSpeechId;
int _lastSpeaker;
uint32 _activeVoiceFileTotalTime;
int _lastSfxTrack;
int _lastMusicTrack;
int _curMusicFileIndex;
char _curMusicFileExt;
int _environmentSfx;
int _environmentSfxVol;
int _envSfxDistThreshold;
bool _envSfxUseQueue;
int _envSfxNumTracksInQueue;
uint16 _envSfxQueuedTracks[10];
uint16 _envSfxQueuedBlocks[10];
int _nextSpeechId;
int _nextSpeaker;
typedef Common::List<Audio::SeekableAudioStream *> SpeechList;
typedef Common::List<Audio::SeekableAudioStream*> SpeechList;
SpeechList _speechList;
int _curTlkFile;
@ -502,9 +464,7 @@ private:
int _ingameSoundListSize;
const uint8 *_musicTrackMap;
int _musicTrackMapSize;
const uint16 *_ingameSoundIndex;
int _ingameSoundIndexSize;
const uint8 *_ingameGMSoundIndex;
int _ingameGMSoundIndexSize;
const uint8 *_ingameMT32SoundIndex;
@ -519,7 +479,6 @@ private:
void gui_drawScene(int pageNum);
void gui_drawAllCharPortraitsWithStats();
void gui_drawCharPortraitWithStats(int charNum);
void gui_drawBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor);
void gui_drawCharFaceShape(int charNum, int x, int y, int pageNum);
void gui_highlightPortraitFrame(int charNum);
void gui_drawLiveMagicBar(int x, int y, int curPoints, int unk, int maxPoints, int w, int h, int col1, int col2, int flag);
@ -534,7 +493,6 @@ private:
void gui_printCharacterStats(int index, int redraw, int value);
void gui_changeCharacterStats(int charNum);
void gui_drawCharInventoryItem(int itemIndex);
void gui_drawBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2);
int gui_enableControls();
int gui_disableControls(int controlMode);
@ -548,37 +506,27 @@ private:
int _lastButtonShape;
uint32 _buttonPressTimer;
int _selectedCharacter;
int _compassDirection;
int _compassStep;
int _compassDirectionIndex;
uint32 _compassTimer;
int _charInventoryUnk;
const CompassDef *_compassDefs;
int _compassDefsSize;
void gui_updateInput();
void gui_triggerEvent(int eventType);
void removeInputTop();
void gui_enableDefaultPlayfieldButtons();
void gui_enableSequenceButtons(int x, int y, int w, int h, int enableFlags);
void gui_specialSceneRestoreButtons();
void gui_enableCharInventoryButtons(int charNum);
void gui_resetButtonList();
void gui_initButtonsFromList(const int16 *list);
void gui_setFaceFramesControlButtons(int index, int xOffs);
void gui_initCharInventorySpecialButtons(int charNum);
void gui_initMagicScrollButtons();
void gui_initMagicSubmenu(int charNum);
void gui_initButton(int index, int x = -1, int y = -1, int val = -1);
void gui_notifyButtonListChanged();
Common::Array<Button::Callback> _buttonCallbacks;
Button *_activeButtons;
Button _activeButtonData[70];
ButtonDef _sceneWindowButton;
bool _preserveEvents;
LoLButtonDef _sceneWindowButton;
int clickedUpArrow(Button *button);
int clickedDownArrow(Button *button);
@ -613,45 +561,34 @@ private:
int clickedLamp(Button *button);
int clickedStatusIcon(Button *button);
const ButtonDef *_buttonData;
int _buttonDataSize;
Common::Array<Button::Callback> _buttonCallbacks;
const LoLButtonDef *_buttonData;
const int16 *_buttonList1;
int _buttonList1Size;
const int16 *_buttonList2;
int _buttonList2Size;
const int16 *_buttonList3;
int _buttonList3Size;
const int16 *_buttonList4;
int _buttonList4Size;
const int16 *_buttonList5;
int _buttonList5Size;
const int16 *_buttonList6;
int _buttonList6Size;
const int16 *_buttonList7;
int _buttonList7Size;
const int16 *_buttonList8;
int _buttonList8Size;
// text
int characterSays(int track, int charId, bool redraw);
int playCharacterScriptChat(int charId, int mode, int restorePortrait, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
void setupDialogueButtons(int numStr, const char *s1, const char *s2, const char *s3);
TextDisplayer_LoL *_txt;
TextDisplayer_Eob *txt() { return _txt; }
// emc scripts
void runInitScript(const char *filename, int optionalFunc);
void runInfScript(const char *filename);
void runLevelScript(int block, int flags);
void runLevelScriptCustom(int block, int flags, int charNum, int item, int reg3, int reg4);
bool checkSceneUpdateNeed(int func);
EMCData _scriptData;
bool _suspendScript;
uint16 _scriptDirection;
uint16 _currentDirection;
uint16 _currentBlock;
bool _sceneUpdateRequired;
int16 _visibleBlockIndex[18];
int16 _globalScriptVars[24];
// emc opcode
@ -702,7 +639,7 @@ private:
int olol_checkEquippedItemScriptFlags(EMCState *script);
int olol_setDoorState(EMCState *script);
int olol_updateBlockAnimations(EMCState *script);
int olol_mapShapeToBlock(EMCState *script);
int olol_assignLevelDecorationShape(EMCState *script);
int olol_resetBlockShapeAssignment(EMCState *script);
int olol_copyRegion(EMCState *script);
int olol_initMonster(EMCState *script);
@ -716,7 +653,7 @@ private:
int olol_battleHitSkillTest(EMCState *script);
int olol_inflictDamage(EMCState *script);
int olol_moveMonster(EMCState *script);
int olol_dialogueBox(EMCState *script);
int olol_setupDialogueButtons(EMCState *script);
int olol_giveTakeMoney(EMCState *script);
int olol_checkMoney(EMCState *script);
int olol_setScriptTimer(EMCState *script);
@ -792,7 +729,7 @@ private:
int olol_assignCustomSfx(EMCState *script);
int olol_findAssignedMonster(EMCState *script);
int olol_checkBlockForMonster(EMCState *script);
int olol_transformRegion(EMCState *script);
int olol_crossFadeRegion(EMCState *script);
int olol_calcCoordinatesAddDirectionOffset(EMCState *script);
int olol_resetPortraitsAndDisableSysTimer(EMCState *script);
int olol_enableSysTimer(EMCState *script);
@ -820,7 +757,7 @@ private:
int olol_shakeScene(EMCState *script);
int olol_gasExplosion(EMCState *script);
int olol_calcNewBlockPosition(EMCState *script);
int olol_fadeScene(EMCState *script);
int olol_crossFadeScene(EMCState *script);
int olol_updateDrawPage2(EMCState *script);
int olol_setMouseCursor(EMCState *script);
int olol_characterSays(EMCState *script);
@ -834,14 +771,14 @@ private:
// tim opcode
void setupOpcodeTable();
Common::Array<const TIMOpcode *> _timIntroOpcodes;
Common::Array<const TIMOpcode*> _timIntroOpcodes;
int tlol_setupPaletteFade(const TIM *tim, const uint16 *param);
int tlol_loadPalette(const TIM *tim, const uint16 *param);
int tlol_setupPaletteFadeEx(const TIM *tim, const uint16 *param);
int tlol_processWsaFrame(const TIM *tim, const uint16 *param);
int tlol_displayText(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode *> _timOutroOpcodes;
Common::Array<const TIMOpcode*> _timOutroOpcodes;
int tlol_fadeInScene(const TIM *tim, const uint16 *param);
int tlol_unusedResourceFunc(const TIM *tim, const uint16 *param);
int tlol_fadeInPalette(const TIM *tim, const uint16 *param);
@ -850,7 +787,7 @@ private:
int tlol_delayForChat(const TIM *tim, const uint16 *param);
int tlol_fadeOutSound(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode *> _timIngameOpcodes;
Common::Array<const TIMOpcode*> _timIngameOpcodes;
int tlol_initSceneWindowDialogue(const TIM *tim, const uint16 *param);
int tlol_restoreAfterSceneWindowDialogue(const TIM *tim, const uint16 *param);
int tlol_giveItem(const TIM *tim, const uint16 *param);
@ -900,7 +837,6 @@ private:
void createTransparencyTables();
void updateSequenceBackgroundAnimations();
bool _dialogueField;
uint8 **_itemIconShapes;
int _numItemIconShapes;
uint8 **_itemShapes;
@ -913,7 +849,6 @@ private:
int _numEffectShapes;
const int8 *_gameShapeMap;
int _gameShapeMapSize;
uint8 *_characterFaceShapes[40][3];
@ -942,19 +877,13 @@ private:
LoLCharacter *_characters;
uint16 _activeCharsXpos[3];
int _updateFlags;
int _updateCharNum;
int _updatePortraitSpeechAnimDuration;
int _portraitSpeechAnimMode;
int _resetPortraitAfterSpeechAnim;
int _textColorFlag;
bool _fadeText;
int _needSceneRestore;
uint32 _palUpdateTimer;
uint32 _updatePortraitNext;
int _loadLevelFlag;
int _hasTempDataFlags;
int _activeMagicMenu;
uint16 _scriptCharacterCycle;
int _charStatsTemp[5];
@ -963,15 +892,10 @@ private:
int _charDefaultsSize;
const uint16 *_charDefsMan;
int _charDefsManSize;
const uint16 *_charDefsWoman;
int _charDefsWomanSize;
const uint16 *_charDefsKieran;
int _charDefsKieranSize;
const uint16 *_charDefsAkshel;
int _charDefsAkshelSize;
const int32 *_expRequirements;
int _expRequirementsSize;
// lamp
void resetLampStatus();
@ -983,16 +907,14 @@ private:
int _lampOilStatus;
uint32 _lampStatusTimer;
bool _lampStatusSuspended;
uint8 _blockBrightness;
// level
void loadLevel(int index);
void addLevelItems();
void loadLevelWallData(int index, bool mapShapes);
void loadLevelWallData(int fileIndex, bool mapShapes);
void assignBlockObject(LevelBlockProperty *l, uint16 item);
int assignLevelShapes(int index);
uint8 *getLevelShapes(int index);
void restoreBlockTempData(int index);
int assignLevelDecorationShapes(int index);
uint8 *getLevelDecorationShapes(int index);
void restoreTempDataAdjustMonsterStrength(int index);
void loadBlockProperties(const char *cmzFile);
void loadLevelShpDat(const char *shpFile, const char *datFile, bool flag);
@ -1006,17 +928,7 @@ private:
void drawScene(int pageNum);
void generateBlockDrawingBuffer();
void generateVmpTileData(int16 startBlockX, uint8 startBlockY, uint8 wllVmpIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY);
void generateVmpTileDataFlipped(int16 startBlockX, uint8 startBlockY, uint8 wllVmpIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY);
bool hasWall(int index);
void assignVisibleBlocks(int block, int direction);
void drawVcnBlocks();
void drawSceneShapes();
void setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim);
void scaleLevelShapesDim(int index, int16 &y1, int16 &y2, int dim);
void drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2);
void drawDecorations(int index);
void drawBlockEffects(int index, int type);
void drawSpecialGuiShape(int pageNum);
@ -1033,27 +945,17 @@ private:
void updateCompass();
void moveParty(uint16 direction, int unk1, int unk2, int buttonShape);
bool checkBlockPassability(uint16 block, uint16 direction);
void notifyBlockNotPassable(int scrollFlag);
virtual bool checkBlockPassability(uint16 block, uint16 direction);
uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction);
uint16 calcBlockIndex(uint16 x, uint16 y);
void calcCoordinates(uint16 &x, uint16 &y, int block, uint16 xOffs, uint16 yOffs);
void calcCoordinatesForSingleCharacter(int charNum, uint16 &x, uint16 &y);
void calcCoordinatesAddDirectionOffset(uint16 &x, uint16 &y, int direction);
int clickedWallShape(uint16 block, uint16 direction);
int clickedLeverOn(uint16 block, uint16 direction);
int clickedLeverOff(uint16 block, uint16 direction);
int clickedWallOnlyScript(uint16 block);
int clickedDoorSwitch(uint16 block, uint16 direction);
int clickedNiche(uint16 block, uint16 direction);
bool clickedShape(int shapeIndex);
void processDoorSwitch(uint16 block, int unk);
void openCloseDoor(uint16 block, int openClose);
void completeDoorOperations();
void movePartySmoothScrollBlocked(int speed);
void movePartySmoothScrollUp(int speed);
void movePartySmoothScrollDown(int speed);
@ -1069,79 +971,40 @@ private:
int smoothScrollDrawSpecialGuiShape(int pageNum);
OpenDoorState _openDoorState[3];
int _blockDoor;
int _smoothScrollModeNormal;
const uint8 *_scrollXTop;
int _scrollXTopSize;
const uint8 *_scrollYTop;
int _scrollYTopSize;
const uint8 *_scrollXBottom;
int _scrollXBottomSize;
const uint8 *_scrollYBottom;
int _scrollYBottomSize;
int _nextScriptFunc;
uint8 _currentLevel;
int _sceneDefaultUpdate;
int _lvlBlockIndex;
int _lvlShapeIndex;
bool _partyAwake;
uint8 *_vcnBlocks;
uint8 *_vcnShift;
uint8 *_vcnExpTable;
uint16 *_vmpPtr;
uint8 *_vcfBlocks;
uint16 *_blockDrawingBuffer;
uint8 *_sceneWindowBuffer;
LevelShapeProperty *_levelShapeProperties;
uint8 **_levelShapes;
uint8 *_specialGuiShape;
uint16 _specialGuiShapeX;
uint16 _specialGuiShapeY;
uint16 _specialGuiShapeMirrorFlag;
char _lastBlockDataFile[12];
char _lastOverridePalFile[12];
char *_lastOverridePalFilePtr;
int _lastSpecialColor;
int _lastSpecialColorWeight;
int _sceneDrawVarDown;
int _sceneDrawVarRight;
int _sceneDrawVarLeft;
int _wllProcessFlag;
uint8 *_transparencyTable2;
uint8 *_transparencyTable1;
int _loadSuppFilesFlag;
uint8 *_wllVmpMap;
int8 *_wllShapeMap;
uint8 *_specialWallTypes;
uint8 *_wllBuffer4;
uint8 *_wllWallFlags;
int16 *_lvlShapeTop;
int16 *_lvlShapeBottom;
int16 *_lvlShapeLeftRight;
LevelBlockProperty *_levelBlockProperties;
LevelBlockProperty *_visibleBlocks[18];
uint8 *_wllAutomapData;
uint16 _partyPosX;
uint16 _partyPosY;
Common::SeekableReadStream *_lvlShpFileHandle;
uint16 _lvlShpNum;
uint16 _levelFileDataSize;
LevelShapeProperty *_levelFileData;
uint8 *_doorShapes[2];
int _shpDmX;
int _shpDmY;
uint16 _dmScaleW;
@ -1154,55 +1017,20 @@ private:
uint8 *_tempBuffer5120;
const char * const *_levelDatList;
int _levelDatListSize;
const char * const *_levelShpList;
int _levelShpListSize;
const int8 *_dscUnk1;
int _dscUnk1Size;
const int8 *_dscShapeIndex;
int _dscShapeIndexSize;
const int8 *_dscWalls;
const uint8 *_dscOvlMap;
int _dscOvlMapSize;
const uint16 *_dscShapeScaleW;
int _dscShapeScaleWSize;
const uint16 *_dscShapeScaleH;
int _dscShapeScaleHSize;
const int16 *_dscShapeX;
int _dscShapeXSize;
const int8 *_dscShapeY;
int _dscShapeYSize;
const uint8 *_dscTileIndex;
int _dscTileIndexSize;
const uint8 *_dscUnk2;
int _dscUnk2Size;
const uint8 *_dscDoorShpIndex;
int _dscDoorShpIndexSize;
const int8 *_dscDim1;
int _dscDim1Size;
const int8 *_dscDim2;
int _dscDim2Size;
const uint8 *_dscBlockMap;
int _dscBlockMapSize;
const uint8 *_dscDimMap;
int _dscDimMapSize;
const uint16 *_dscDoorMonsterScaleTable;
int _dscDoorMonsterScaleTableSize;
const uint16 *_dscDoor4;
int _dscDoor4Size;
const uint8 *_dscShapeOvlIndex;
int _dscShapeOvlIndexSize;
const int8 *_dscBlockIndex;
int _dscBlockIndexSize;
const uint8 *_dscDoor1;
int _dscDoor1Size;
const int16 *_dscDoorMonsterX;
int _dscDoorMonsterXSize;
const int16 *_dscDoorMonsterY;
int _dscDoorMonsterYSize;
const uint16 *_dscShapeScaleW;
const uint16 *_dscShapeScaleH;
const int8 *_dscShapeY;
int _sceneDrawPage1;
int _sceneDrawPage2;
const uint16 *_dscDoorMonsterScaleTable;
const uint16 *_dscDoor4;
const int16 *_dscDoorMonsterX;
const int16 *_dscDoorMonsterY;
// items
void giveCredits(int credits, int redraw);
@ -1239,8 +1067,7 @@ private:
Item _itemInHand;
Item _inventory[48];
Item _inventoryCurItem;
int _currentControlMode;
int _specialSceneFlag;
int _lastCharInventory;
uint16 _charStatusFlags[3];
int _emcLastItem;
@ -1250,34 +1077,27 @@ private:
EMCData _itemScript;
const uint8 *_charInvIndex;
int _charInvIndexSize;
const uint8 *_charInvDefs;
int _charInvDefsSize;
const uint16 *_inventorySlotDesc;
int _inventorySlotDescSize;
const uint16 *_itemCost;
int _itemCostSize;
const uint8 *_stashSetupData;
int _stashSetupDataSize;
const int8 *_sceneItemOffs;
int _sceneItemOffsSize;
const FlyingObjectShape *_flyingItemShapes;
int _flyingItemShapesSize;
// monsters
void loadMonsterShapes(const char *file, int monsterIndex, int b);
void releaseMonsterShapes(int monsterIndex);
int deleteMonstersFromBlock(int block);
void setMonsterMode(MonsterInPlay *monster, int mode);
bool updateMonsterAdjustBlocks(MonsterInPlay *monster);
void placeMonster(MonsterInPlay *monster, uint16 x, uint16 y);
void setMonsterMode(LolMonsterInPlay *monster, int mode);
bool updateMonsterAdjustBlocks(LolMonsterInPlay *monster);
void placeMonster(LolMonsterInPlay *monster, uint16 x, uint16 y);
int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void setMonsterDirection(MonsterInPlay *monster, int dir);
void monsterDropItems(MonsterInPlay *monster);
void setMonsterDirection(LolMonsterInPlay *monster, int dir);
void monsterDropItems(LolMonsterInPlay *monster);
void removeAssignedObjectFromBlock(LevelBlockProperty *l, uint16 id);
void removeDrawObjectFromBlock(LevelBlockProperty *l, uint16 id);
void assignMonsterToBlock(uint16 *assignedBlockObjects, uint16 id);
void giveItemToMonster(MonsterInPlay *monster, Item item);
void giveItemToMonster(LolMonsterInPlay *monster, Item item);
int checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 objectWidth, uint16 testFlag, uint16 wallFlag);
int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int objectWidth, int testFlag, int wallFlag);
int calcMonsterSkillLevel(int id, int a);
@ -1288,7 +1108,7 @@ private:
void drawBlockObjects(int blockArrayIndex);
void drawMonster(uint16 id);
int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags);
int getMonsterCurFrame(LolMonsterInPlay *m, uint16 dirFlags);
void reassignDrawObjects(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag);
void redrawSceneItem();
int calcItemMonsterPosition(ItemInPlay *i, uint16 direction);
@ -1298,47 +1118,35 @@ private:
uint8 *drawItemOrMonster(uint8 *shape, uint8 *monsterPalette, int x, int y, int fineX, int fineY, int flags, int tblValue, bool vflip);
int calcDrawingLayerParameters(int srcX, int srcY, int &x2, int &y2, uint16 &w, uint16 &h, uint8 *shape, int vflip);
void updateMonster(MonsterInPlay *monster);
void moveMonster(MonsterInPlay *monster);
void walkMonster(MonsterInPlay *monster);
bool chasePartyWithDistanceAttacks(MonsterInPlay *monster);
void chasePartyWithCloseAttacks(MonsterInPlay *monster);
int walkMonsterCalcNextStep(MonsterInPlay *monster);
int getMonsterDistance(uint16 block1, uint16 block2);
void updateMonster(LolMonsterInPlay *monster);
void moveMonster(LolMonsterInPlay *monster);
void walkMonster(LolMonsterInPlay *monster);
bool chasePartyWithDistanceAttacks(LolMonsterInPlay *monster);
void chasePartyWithCloseAttacks(LolMonsterInPlay *monster);
int walkMonsterCalcNextStep(LolMonsterInPlay *monster);
int checkForPossibleDistanceAttack(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk);
int walkMonsterCheckDest(int x, int y, LolMonsterInPlay *monster, int unk);
void getNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 direction);
void rearrangeAttackingMonster(MonsterInPlay *monster);
void moveStrayingMonster(MonsterInPlay *monster);
void killMonster(MonsterInPlay *monster);
void rearrangeAttackingMonster(LolMonsterInPlay *monster);
void moveStrayingMonster(LolMonsterInPlay *monster);
void killMonster(LolMonsterInPlay *monster);
MonsterInPlay *_monsters;
MonsterProperty *_monsterProperties;
uint8 **_monsterShapes;
uint8 **_monsterPalettes;
uint8 **_monsterShapesEx;
LolMonsterInPlay *_monsters;
LolMonsterProperty *_monsterProperties;
uint8 **_monsterDecorationShapes;
uint8 _monsterAnimType[3];
uint16 _monsterCurBlock;
int _objectLastDirection;
int _monsterStepCounter;
int _monsterStepMode;
const uint16 *_monsterModifiers;
int _monsterModifiersSize;
const int8 *_monsterShiftOffs;
int _monsterShiftOffsSize;
const uint8 *_monsterDirFlags;
int _monsterDirFlagsSize;
const uint8 *_monsterScaleX;
int _monsterScaleXSize;
const uint8 *_monsterScaleY;
int _monsterScaleYSize;
const uint16 *_monsterScaleWH;
int _monsterScaleWHSize;
// misc
void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false);
int rollDice(int times, int pips);
uint8 _compassBroken;
uint8 _drainMagic;
@ -1349,7 +1157,7 @@ private:
// spells
typedef Common::Functor1Mem<ActiveSpell *, int, LoLEngine> SpellProc;
Common::Array<const SpellProc *> _spellProcs;
Common::Array<const SpellProc*> _spellProcs;
typedef void (LoLEngine::*SpellProcCallback)(WSAMovie_v2 *, int, int);
int castSpell(int charNum, int spellType, int spellLevel);
@ -1398,7 +1206,7 @@ private:
int8 _availableSpells[8];
int _selectedSpell;
const SpellProperty *_spellProperties;
int _spellPropertiesSize;
//int _spellPropertiesSize;
int _subMenuIndex;
LightningProperty *_lightningProps;
@ -1420,13 +1228,9 @@ private:
static const MistOfDoomAnimData _mistAnimData[];
const uint8 *_updateSpellBookCoords;
int _updateSpellBookCoordsSize;
const uint8 *_updateSpellBookAnimData;
int _updateSpellBookAnimDataSize;
const uint8 *_healShapeFrames;
int _healShapeFramesSize;
const int16 *_fireBallCoords;
int _fireBallCoordsSize;
// fight
int battleHitSkillTest(int16 attacker, int16 target, int skill);
@ -1437,8 +1241,8 @@ private:
int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType);
void checkForPartyDeath();
void applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage);
void applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int flags, int skill, int damage);
void applyMonsterAttackSkill(LolMonsterInPlay *monster, int16 target, int16 damage);
void applyMonsterDefenseSkill(LolMonsterInPlay *monster, int16 attacker, int flags, int skill, int damage);
int removeCharacterItem(int charNum, int itemFlags);
int paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw);
void paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance);
@ -1478,7 +1282,6 @@ private:
uint8 *_mapOverlay;
const uint8 **_automapShapes;
const uint16 *_autoMapStrings;
int _autoMapStringsSize;
MapLegendData *_defaultLegendData;
uint8 *_mapCursorOverlay;
uint8 _automapTopLeftX;
@ -1495,10 +1298,15 @@ private:
Common::Error loadGameState(int slot);
Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail);
Graphics::Surface *generateSaveThumbnail() const;
void *generateMonsterTempData(LevelTempData *tmp);
void *generateFlyingObjectTempData(LevelTempData *tmp);
void restoreBlockTempData(int levelIndex);
void restoreMonsterTempData(LevelTempData *tmp);
void restoreFlyingObjectTempData(LevelTempData *tmp);
void releaseMonsterTempData(LevelTempData *tmp);
void releaseFlyingObjectTempData(LevelTempData *tmp);
void generateTempData();
LevelTempData *_lvlTempData[29];
Graphics::Surface *generateSaveThumbnail() const;
};
class HistoryPlayer {

354
engines/kyra/loleobbase.cpp Normal file
View File

@ -0,0 +1,354 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/loleobbase.h"
#include "kyra/sound.h"
#include "common/system.h"
namespace Kyra {
LolEobBaseEngine::LolEobBaseEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(system, flags) {
_txt = 0;
_mouseClick = 0;
_preserveEvents = _buttonListChanged = false;
_sceneXoffset = 0;
_sceneShpDim = 5;
_activeButtons = 0;
_currentLevel = 0;
_vmpPtr = 0;
_vcnBlocks = 0;
_vcfBlocks = 0;
_vcnShift = 0;
_vcnExpTable = 0;
_vmpPtr = 0;
_blockBrightness = _wllVcnOffset = 0;
_blockDrawingBuffer = 0;
_sceneWindowBuffer = 0;
_monsterShapes = _monsterPalettes = 0;
_doorShapes = 0;
_levelDecorationProperties = 0;
_levelDecorationData = 0;
_levelDecorationShapes = 0;
_decorationCount = 0;
_mappedDecorationsCount = 0;
memset(_visibleBlockIndex, 0, sizeof(_visibleBlockIndex));
_lvlShapeTop = _lvlShapeBottom = _lvlShapeLeftRight = 0;
_levelBlockProperties = 0;
_hasTempDataFlags = 0;
_wllVmpMap = _specialWallTypes = _wllWallFlags = 0;
_wllShapeMap = 0;
_sceneDrawVarDown = _sceneDrawVarRight = _sceneDrawVarLeft = _wllProcessFlag = 0;
_currentBlock = 0;
_currentDirection = 0;
_compassDirection = -1;
_updateFlags = _clickedSpecialFlag = 0;
_sceneDefaultUpdate = 0;
_sceneUpdateRequired = false;
_clickedShapeXOffs = _clickedShapeYOffs = 0;
_dscShapeX = 0;
_dscTileIndex = 0;
_dscUnk2 = 0;
_dscDim1 = 0;
_dscDim2 = 0;
_dscBlockMap = 0;
_dscBlockIndex = 0;
_dscShapeIndex = 0;
_dscDimMap = 0;
_dscDoorShpIndex = 0;
_dscDoorY2 = 0;
_shpDmX1 = _shpDmX2 = 0;
memset(_openDoorState, 0, sizeof(_openDoorState));
memset(_dialogueButtonString, 0, 3 * sizeof(const char *));
_dialogueButtonPosX = 0;
_dialogueButtonPosY = 0;
_dialogueNumButtons = _dialogueButtonYoffs = _dialogueHighlightedButton = 0;
_currentControlMode = 0;
_specialSceneFlag = 0;
_dialogueButtonLabelCol1 = 9;
_dialogueButtonLabelCol2 = 15;
_dialogueButtonW = 95;
_dialogueButtonH = 9;
_updateCharNum = -1;
_activeVoiceFileTotalTime = 0;
_updatePortraitSpeechAnimDuration = _resetPortraitAfterSpeechAnim = _needSceneRestore = 0;
_fadeText = false;
memset(_lvlTempData, 0, sizeof(_lvlTempData));
_dialogueField = false;
_environmentSfx = _environmentSfxVol = _envSfxDistThreshold = 0;
_monsterStepCounter = _monsterStepMode = 0;
}
LolEobBaseEngine::~LolEobBaseEngine() {
delete[] _wllVmpMap;
delete[] _wllShapeMap;
delete[] _specialWallTypes;
delete[] _wllWallFlags;
delete[] _vmpPtr;
delete[] _vcnExpTable;
delete[] _vcnBlocks;
delete[] _vcfBlocks;
delete[] _vcnShift;
delete[] _blockDrawingBuffer;
delete[] _sceneWindowBuffer;
delete[] _lvlShapeTop;
delete[] _lvlShapeBottom;
delete[] _lvlShapeLeftRight;
delete[] _doorShapes;
delete[] _levelDecorationShapes;
delete[] _levelDecorationData;
delete[] _levelDecorationProperties;
delete[] _levelBlockProperties;
delete _txt;
_txt = 0;
}
Common::Error LolEobBaseEngine::init() {
_levelDecorationProperties = new LevelDecorationProperty[100];
memset(_levelDecorationProperties, 0, 100 * sizeof(LevelDecorationProperty));
_levelDecorationShapes = new uint8*[400];
memset(_levelDecorationShapes, 0, 400 * sizeof(uint8*));
_levelBlockProperties = new LevelBlockProperty[1025];
memset(_levelBlockProperties, 0, 1025 * sizeof(LevelBlockProperty));
_wllVmpMap = new uint8[255];
memset(_wllVmpMap, 0, 255);
_wllShapeMap = new int8[255];
memset(_wllShapeMap, 0, 255);
_specialWallTypes = new uint8[255];
memset(_specialWallTypes, 0, 255);
_wllWallFlags = new uint8[255];
memset(_wllWallFlags, 0, 255);
_blockDrawingBuffer = new uint16[1320];
memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16));
_sceneWindowBuffer = new uint8[21120];
memset(_sceneWindowBuffer, 0, 21120);
_lvlShapeTop = new int16[18];
memset(_lvlShapeTop, 0, 18 * sizeof(int16));
_lvlShapeBottom = new int16[18];
memset(_lvlShapeBottom, 0, 18 * sizeof(int16));
_lvlShapeLeftRight = new int16[36];
memset(_lvlShapeLeftRight, 0, 36 * sizeof(int16));
_vcnExpTable = new uint8[128];
for (int i = 0; i < 128; i++)
_vcnExpTable[i] = i & 0x0f;
_doorShapes = new uint8*[6];
memset(_doorShapes, 0, 6 * sizeof(uint8*));
initStaticResource();
_envSfxDistThreshold = (_sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : 3;
return Common::kNoError;
}
bool LolEobBaseEngine::posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2) {
if (mouseX < x1 || mouseX > x2 || mouseY < y1 || mouseY > y2)
return false;
return true;
}
void LolEobBaseEngine::drawDialogueButtons() {
int cp = screen()->setCurPage(0);
Screen::FontId of = screen()->setFont(gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
for (int i = 0; i < _dialogueNumButtons; i++) {
int x = _dialogueButtonPosX[i];
if (gameFlags().use16ColorMode) {
gui_drawBox(x, ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1, 74, 10, 0xee, 0xcc, -1);
screen()->printText(_dialogueButtonString[i], (x + 37 - (screen()->getTextWidth(_dialogueButtonString[i])) / 2) & ~3,
((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xc1 : 0xe1, 0);
} else {
gui_drawBox(x, (_dialogueButtonYoffs + _dialogueButtonPosY[i]), _dialogueButtonW, _dialogueButtonH, _color1_1, _color2_1, _bkgColor_1);
screen()->printText(_dialogueButtonString[i], x + (_dialogueButtonW >> 1) - (screen()->getTextWidth(_dialogueButtonString[i])) / 2,
(_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2, _dialogueHighlightedButton == i ? _dialogueButtonLabelCol1 : _dialogueButtonLabelCol2, 0);
}
}
screen()->setFont(of);
screen()->setCurPage(cp);
}
uint16 LolEobBaseEngine::processDialogue() {
int df = _dialogueHighlightedButton;
int res = 0;
for (int i = 0; i < _dialogueNumButtons; i++) {
int x = _dialogueButtonPosX[i];
int y = (gameFlags().use16ColorMode ? ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1 : (_dialogueButtonYoffs + _dialogueButtonPosY[i]));
Common::Point p = getMousePos();
if (posWithinRect(p.x, p.y, x, y, x + _dialogueButtonW, y + _dialogueButtonH)) {
_dialogueHighlightedButton = i;
break;
}
}
if (_dialogueNumButtons == 0) {
int e = checkInput(0, false) & 0xFF;
removeInputTop();
if (e) {
gui_notifyButtonListChanged();
if (e == _keyMap[Common::KEYCODE_SPACE] || e == _keyMap[Common::KEYCODE_RETURN]) {
snd_stopSpeech(true);
}
}
if (snd_updateCharacterSpeech() != 2) {
res = 1;
if (!shouldQuit()) {
removeInputTop();
gui_notifyButtonListChanged();
}
}
} else {
int e = checkInput(0, false) & 0xFF;
removeInputTop();
if (e)
gui_notifyButtonListChanged();
if (_flags.gameID == GI_LOL && (e == 200 || e == 202) || _flags.gameID != GI_LOL && (e == 199 || e == 201)) {
for (int i = 0; i < _dialogueNumButtons; i++) {
int x = _dialogueButtonPosX[i];
int y = (gameFlags().use16ColorMode ? ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1 : (_dialogueButtonYoffs + _dialogueButtonPosY[i]));
Common::Point p = getMousePos();
if (posWithinRect(p.x, p.y, x, y, x + _dialogueButtonW, y + _dialogueButtonH)) {
_dialogueHighlightedButton = i;
res = _dialogueHighlightedButton + 1;
break;
}
}
} else if (e == _keyMap[Common::KEYCODE_SPACE] || e == _keyMap[Common::KEYCODE_RETURN]) {
snd_stopSpeech(true);
res = _dialogueHighlightedButton + 1;
} else if (e == _keyMap[Common::KEYCODE_LEFT] || e == _keyMap[Common::KEYCODE_DOWN]) {
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton > 0)
_dialogueHighlightedButton--;
} else if (e == _keyMap[Common::KEYCODE_RIGHT] || e == _keyMap[Common::KEYCODE_UP]) {
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton < (_dialogueNumButtons - 1))
_dialogueHighlightedButton++;
}
}
if (df != _dialogueHighlightedButton)
drawDialogueButtons();
screen()->updateScreen();
if (res == 0)
return 0;
stopPortraitSpeechAnim();
if (game() == GI_LOL) {
if (!textEnabled() && _currentControlMode) {
screen()->setScreenDim(5);
const ScreenDim *d = screen()->getScreenDim(5);
screen()->fillRect(d->sx, d->sy + d->h - 9, d->sx + d->w - 1, d->sy + d->h - 1, d->unkA);
} else {
const ScreenDim *d = screen()->_curDim;
if (gameFlags().use16ColorMode)
screen()->fillRect(d->sx, d->sy, d->sx + d->w - 3, d->sy + d->h - 2, d->unkA);
else
screen()->fillRect(d->sx, d->sy, d->sx + d->w - 2, d->sy + d->h - 1, d->unkA);
txt()->clearDim(4);
txt()->resetDimTextPositions(4);
}
}
return res;
}
void LolEobBaseEngine::delayUntil(uint32 time, bool doUpdate, bool isMainLoop) {
uint32 curTime = _system->getMillis();
if (time > curTime)
delay(time - curTime, doUpdate, isMainLoop);
}
int LolEobBaseEngine::rollDice(int times, int pips, int inc) {
if (times <= 0 || pips <= 0)
return inc;
int res = 0;
while (times--)
res += _rnd.getRandomNumberRng(1, pips);
return res + inc;
}
bool LolEobBaseEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
if (!_sound->sfxEnabled() || shouldQuit())
return false;
if (_environmentSfx)
snd_playSoundEffect(_environmentSfx, _environmentSfxVol);
int dist = 0;
if (block) {
dist = getBlockDistance(_currentBlock, block);
if (dist > _envSfxDistThreshold) {
_environmentSfx = 0;
return false;
}
}
_environmentSfx = soundId;
_environmentSfxVol = (15 - ((block || (_flags.gameID == GI_LOL && dist < 2)) ? dist : 0)) << 4;
return true;
}
void LolEobBaseEngine::updateEnvironmentalSfx(int soundId) {
snd_processEnvironmentalSoundEffect(soundId, _currentBlock);
}
} // End of namespace Kyra
#endif // ENABLE_EOB || ENABLE_LOL

324
engines/kyra/loleobbase.h Normal file
View File

@ -0,0 +1,324 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef KYRA_LOLEOBBASE_H
#define KYRA_LOLEOBBASE_H
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/kyra_v1.h"
#include "kyra/screen_eob.h"
#include "kyra/gui_eob.h"
#include "kyra/text_lol.h"
namespace Kyra {
struct LevelDecorationProperty {
uint16 shapeIndex[10];
uint8 scaleFlag[10];
int16 shapeX[10];
int16 shapeY[10];
int8 next;
uint8 flags;
};
struct LevelBlockProperty {
uint8 walls[4];
uint16 assignedObjects;
uint16 drawObjects;
uint8 direction;
uint16 flags;
};
struct OpenDoorState {
uint16 block;
int8 wall;
int8 state;
};
struct LevelTempData {
uint8 *wallsXorData;
uint16 *flags;
void *monsters;
void *flyingObjects;
uint8 monsterDifficulty;
};
class LolEobBaseEngine : public KyraEngine_v1 {
friend class TextDisplayer_Eob;
public:
LolEobBaseEngine(OSystem *system, const GameFlags &flags);
virtual ~LolEobBaseEngine();
virtual Screen *screen() = 0;
virtual GUI *gui() const = 0;
protected:
// Startup
virtual Common::Error init();
virtual Common::Error go() = 0;
// Init
void initStaticResource();
const uint8 **_itemIconShapes;
// Main loop
virtual void update() = 0;
void updateEnvironmentalSfx(int soundId);
// timers
virtual void setupTimers() = 0;
void enableSysTimer(int sysTimer);
void disableSysTimer(int sysTimer);
void enableTimer(int id);
virtual uint8 getClock2Timer(int index) = 0;
virtual uint8 getNumClock2Timers() = 0;
void timerProcessDoors(int timerNum);
// mouse
bool posWithinRect(int mouseX, int mouseY, int x1, int y1, int x2, int y2);
virtual void setHandItem(Item itemIndex) = 0;
// Characters
int _updateCharNum;
int _updatePortraitSpeechAnimDuration;
bool _fadeText;
int _resetPortraitAfterSpeechAnim;
int _needSceneRestore;
// Items
int _itemInHand;
// Monsters
int getBlockDistance(uint16 block1, uint16 block2);
uint8 **_monsterPalettes;
uint8 **_monsterShapes;
int16 _shpDmX1;
int16 _shpDmX2;
int _monsterStepCounter;
int _monsterStepMode;
// Level
virtual void addLevelItems() = 0;
virtual void loadBlockProperties(const char *file) = 0;
virtual void drawScene(int pageNum) = 0;
virtual void drawSceneShapes() = 0;
virtual void drawDecorations(int index) = 0;
void setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim);
void scaleLevelShapesDim(int index, int16 &y1, int16 &y2, int dim);
void drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2);
void generateBlockDrawingBuffer();
void generateVmpTileData(int16 startBlockX, uint8 startBlockY, uint8 wllVmpIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY);
void generateVmpTileDataFlipped(int16 startBlockX, uint8 startBlockY, uint8 wllVmpIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY);
bool hasWall(int index);
void assignVisibleBlocks(int block, int direction);
bool checkSceneUpdateNeed(int block);
void drawVcnBlocks();
uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction);
virtual int clickedDoorSwitch(uint16 block, uint16 direction) = 0;
int clickedWallShape(uint16 block, uint16 direction);
int clickedLeverOn(uint16 block, uint16 direction);
int clickedLeverOff(uint16 block, uint16 direction);
int clickedWallOnlyScript(uint16 block);
virtual int clickedNiche(uint16 block, uint16 direction) = 0;
void processDoorSwitch(uint16 block, int openClose);
void openCloseDoor(int block, int openClose);
void completeDoorOperations();
uint8 *_wllVmpMap;
int8 *_wllShapeMap;
uint8 *_specialWallTypes;
uint8 *_wllWallFlags;
int _sceneXoffset;
int _sceneShpDim;
LevelBlockProperty *_levelBlockProperties;
LevelBlockProperty *_visibleBlocks[18];
LevelDecorationProperty *_levelDecorationData;
uint16 _levelDecorationDataSize;
LevelDecorationProperty *_levelDecorationProperties;
uint8 **_levelDecorationShapes;
uint16 _decorationCount;
int16 _mappedDecorationsCount;
uint16 *_vmpPtr;
uint8 *_vcnBlocks;
uint8 *_vcfBlocks;
uint8 *_vcnShift;
uint8 *_vcnExpTable;
uint16 *_blockDrawingBuffer;
uint8 *_sceneWindowBuffer;
uint8 _blockBrightness;
uint8 _wllVcnOffset;
uint8 **_doorShapes;
uint8 _currentLevel;
uint16 _currentBlock;
uint16 _currentDirection;
int _sceneDefaultUpdate;
bool _sceneUpdateRequired;
int16 _visibleBlockIndex[18];
int16 *_lvlShapeLeftRight;
int16 *_lvlShapeTop;
int16 *_lvlShapeBottom;
char _lastBlockDataFile[13];
uint32 _hasTempDataFlags;
int16 _sceneDrawVarDown;
int16 _sceneDrawVarRight;
int16 _sceneDrawVarLeft;
int _wllProcessFlag;
OpenDoorState _openDoorState[3];
int _sceneDrawPage1;
int _sceneDrawPage2;
const int8 *_dscShapeIndex;
const uint8 *_dscDimMap;
const int8 *_dscDim1;
const int8 *_dscDim2;
const int16 *_dscShapeX;
const uint8 *_dscUnk2;
const uint8 *_dscBlockMap;
const int8 *_dscBlockIndex;
const uint8 *_dscTileIndex;
const uint8 *_dscDoorShpIndex;
const uint8 *_dscDoorY2;
// Script
virtual void runLevelScript(int block, int flags) = 0;
// Gui
void removeInputTop();
void gui_drawBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor);
virtual void gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2);
void gui_initButtonsFromList(const int16 *list);
virtual void gui_initButton(int index, int x = -1, int y = -1, int val = -1) = 0;
void gui_resetButtonList();
void gui_notifyButtonListChanged();
bool clickedShape(int shapeIndex);
int _clickedShapeXOffs;
int _clickedShapeYOffs;
Button *_activeButtons;
Button _activeButtonData[70];
uint8 _mouseClick;
bool _preserveEvents;
bool _buttonListChanged;
int _updateFlags;
int _clickedSpecialFlag;
int _compassDirection;
static const uint8 _dropItemDirIndex[];
// text
void drawDialogueButtons();
uint16 processDialogue();
TextDisplayer_Eob *_txt;
virtual TextDisplayer_Eob *txt() { return _txt; }
bool _dialogueField;
const char *_dialogueButtonString[9];
const uint16 *_dialogueButtonPosX;
const uint8 *_dialogueButtonPosY;
int16 _dialogueButtonYoffs;
uint16 _dialogueButtonW;
uint16 _dialogueButtonH;
int _dialogueNumButtons;
int _dialogueHighlightedButton;
int _currentControlMode;
int _specialSceneFlag;
uint8 _dialogueButtonLabelCol1;
uint8 _dialogueButtonLabelCol2;
int _bkgColor_1;
uint8 _color1_1;
uint8 _color2_1;
const char *const *_moreStrings;
// misc
virtual void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false) = 0;
void delayUntil(uint32 time, bool doUpdate = false, bool isMainLoop = false);
int rollDice(int times, int pips, int inc = 0);
virtual Common::Error loadGameState(int slot) = 0;
virtual Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) = 0;
void generateTempData();
void restoreBlockTempData(int levelIndex);
void releaseTempData();
virtual void *generateMonsterTempData(LevelTempData *tmp) = 0;
virtual void *generateFlyingObjectTempData(LevelTempData *tmp) = 0;
virtual void restoreMonsterTempData(LevelTempData *tmp) = 0;
virtual void restoreFlyingObjectTempData(LevelTempData *tmp) = 0;
virtual void releaseMonsterTempData(LevelTempData *tmp) = 0;
virtual void releaseFlyingObjectTempData(LevelTempData *tmp) = 0;
LevelTempData *_lvlTempData[29];
// sound
virtual bool snd_processEnvironmentalSoundEffect(int soundId, int block);
virtual void snd_stopSpeech(bool) {}
virtual int snd_updateCharacterSpeech() { return 0; }
virtual void stopPortraitSpeechAnim() {}
virtual void setupOpcodeTable() {}
virtual void snd_playVoiceFile(int) {}
int _environmentSfx;
int _environmentSfxVol;
int _envSfxDistThreshold;
uint32 _activeVoiceFileTotalTime;
// unused
void setWalkspeed(uint8) {}
void removeHandItem() {}
bool lineIsPassable(int, int) { return false; }
};
} // End of namespace Kyra
#endif // ENABLE_EOB || ENABLE_LOL
#endif

780
engines/kyra/magic_eob.cpp Normal file
View File

@ -0,0 +1,780 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#include "kyra/eobcommon.h"
#include "kyra/resource.h"
namespace Kyra {
void EobCoreEngine::useMagicBookOrSymbol(int charIndex, int type) {
EobCharacter *c = &_characters[charIndex];
_openBookSpellLevel = c->slotStatus[3];
_openBookSpellSelectedItem = c->slotStatus[2];
_openBookSpellListOffset = c->slotStatus[4];
_openBookChar = charIndex;
_openBookType = type;
_openBookSpellList = (type == 1) ? _clericSpellList : _mageSpellList;
_openBookAvailableSpells = (type == 1) ? c->clericSpells : c->mageSpells;
int8 *tmp = _openBookAvailableSpells + _openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem;
if (*tmp <= 0) {
for (bool loop = true; loop && _openBookSpellSelectedItem < 10; ) {
tmp = _openBookAvailableSpells + _openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem;
if (*tmp > 0) {
if (_openBookSpellSelectedItem > 5) {
_openBookSpellListOffset = 6;
_openBookSpellSelectedItem -= 6;
}
loop = false;
} else {
_openBookSpellSelectedItem++;
}
}
if (_openBookSpellSelectedItem == 10) {
_openBookSpellListOffset = 0;
_openBookSpellSelectedItem = 6;
}
}
if (!_updateFlags)
_screen->copyRegion(64, 121, 0, 0, 112, 56, 0, 10, Screen::CR_NO_P_CHECK);
_updateFlags = 1;
gui_setPlayFieldButtons();
gui_drawSpellbook();
}
void EobCoreEngine::useMagicScroll(int charIndex, int type, int weaponSlot) {
_openBookCharBackup = _openBookChar;
_openBookTypeBackup = _openBookType;
_castScrollSlot = weaponSlot + 1;
_openBookChar = charIndex;
_openBookType = type <= _clericSpellOffset ? 0 : 1;
castSpell(type, weaponSlot);
}
void EobCoreEngine::usePotion(int charIndex, int weaponSlot) {
EobCharacter *c = &_characters[_openBookChar];
int offset = (_flags.gameID == GI_EOB1) ? 13 : (_flags.lang == Common::DE_DEU ? 19 : 15);
int val = deleteInventoryItem(charIndex, weaponSlot);
snd_playSoundEffect(10);
switch (val) {
case 0:
sparkEffectDefensive(charIndex);
c->strengthCur = 22;
c->strengthExtCur = 0;
setCharEventTimer(charIndex, 546 * rollDice(1, 4, 4), 7, 1);
break;
case 1:
sparkEffectDefensive(charIndex);
modifyCharacterHitpoints(charIndex, rollDice(2, 4, 2));
break;
case 2:
sparkEffectDefensive(charIndex);
modifyCharacterHitpoints(charIndex, rollDice(3, 8, 3));
break;
case 3:
statusAttack(charIndex, 2, _itemExtraStrings[offset], 0, 1, 8, 1);
c->effectFlags &= ~0x2000;
if (c->flags & 2)
return;
break;
case 4:
sparkEffectDefensive(charIndex);
c->food = 100;
if (_currentControlMode)
gui_drawCharPortraitWithStats(charIndex);
break;
case 5:
sparkEffectDefensive(charIndex);
c->effectFlags |= 0x10000;
setCharEventTimer(charIndex, 546 * rollDice(1, 4, 4), 12, 1);
snd_playSoundEffect(100);
gui_drawCharPortraitWithStats(charIndex);
break;
case 6:
sparkEffectDefensive(charIndex);
c->effectFlags |= 0x40;
gui_drawCharPortraitWithStats(charIndex);
break;
case 7:
sparkEffectDefensive(charIndex);
neutralizePoison(charIndex);
break;
default:
break;
}
_txt->printMessage(_itemExtraStrings[offset + 1], -1, c->name, _potionEffectStrings[val]);
}
void EobCoreEngine::castSpell(int spell, int weaponSlot) {
EobSpell *s = &_spells[spell];
EobCharacter *c = &_characters[_openBookChar];
_activeSpell = spell;
if ((s->flags & 0x100) && (c->effectFlags & 0x40))
// remove invisibility effect
removeCharacterEffect(10, _openBookChar, 1);
int ci = _openBookChar;
if (ci > 3)
ci -= 2;
_activeSpellCasterPos = _dropItemDirIndex[(_currentDirection << 2) + ci];
if (s->flags & 0x400) {
if (c->inventory[0] && c->inventory[1]) {
_txt->printMessage(_magicStrings1[2]);
snd_playSoundEffect(79);
return;
}
if (isMagicWeapon(c->inventory[0]) || isMagicWeapon(c->inventory[1])) {
_txt->printMessage(_magicStrings1[3]);
snd_playSoundEffect(79);
return;
}
}
if (!(_flags.gameID == GI_EOB2 && _activeSpell == 62)) {
if (!_castScrollSlot) {
int8 tmp = _openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem];
if (_openBookSpellListOffset + _openBookSpellSelectedItem < 8)
memmove(&_openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem], &_openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem + 1], 8 - (_openBookSpellListOffset + _openBookSpellSelectedItem));
_openBookAvailableSpells[_openBookSpellLevel * 10 + 8] = -tmp;
if (_openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem] < 0) {
if (--_openBookSpellSelectedItem == -1)
if (_openBookSpellListOffset) {
_openBookSpellListOffset = 0;
_openBookSpellSelectedItem = 5;
} else {
_openBookSpellSelectedItem = 6;
}
}
} else if (weaponSlot != -1) {
updateUsedCharacterHandItem(_openBookChar, weaponSlot);
}
}
_txt->printMessage(_magicStrings1[4], -1, c->name, s->name);
if (s->flags & 0x20) {
castOnWhomDialogue();
return;
}
_activeSpellCaster = _openBookChar;
startSpell(spell);
}
void EobCoreEngine::removeCharacterEffect(int spell, int charIndex, int showWarning) {
EobCharacter *c = &_characters[charIndex];
EobSpell *s = &_spells[spell];
if (showWarning) {
_txt->printMessage(_magicStrings3[2], -1, c->name, s->name);
snd_playSoundEffect(79);
}
if (s->endCallback)
(this->*s->endCallback)(0);
if (s->flags & 1)
c->effectFlags &= ~s->effectFlags;
if (s->flags & 4)
_partyEffectFlags &= ~s->effectFlags;
if (s->flags & 0x200) {
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
if (!testCharacter(i, 2) && !(s->flags & 0x800))
continue;
_characters[i].effectFlags &= ~s->effectFlags;
}
}
if (s->flags & 0x2)
recalcArmorClass(_activeSpellCaster);
if (showWarning) {
if (s->flags & 0x20A0)
gui_drawCharPortraitWithStats(charIndex);
else if (s->flags & 0x20A0)
gui_drawAllCharPortraitsWithStats();
}
}
void EobCoreEngine::removeAllCharacterEffects(int charIndex) {
EobCharacter *c = &_characters[charIndex];
memset(c->effectsRemainder, 0, 4);
for (int i = 0; i < 10; i++) {
if (c->events[i] < 0)
removeCharacterEffect(-c->events[i], charIndex, 0);
c->timers[i] = 0;
c->events[i] = 0;
}
setupCharacterTimers();
recalcArmorClass(charIndex);
c->disabledSlots = 0;
c->slotStatus[0] = c->slotStatus[1] = 0;
c->damageTaken = 0;
c->strengthCur = c->strengthMax;
c->strengthExtCur = c->strengthExtMax;
gui_drawAllCharPortraitsWithStats();
}
void EobCoreEngine::castOnWhomDialogue() {
_txt->printMessage(_magicStrings3[0]);
snd_playSoundEffect(79);
gui_setCastOnWhomButtons();
}
void EobCoreEngine::startSpell(int spell) {
EobSpell *s = &_spells[spell];
EobCharacter *c = &_characters[_activeSpellCaster];
snd_playSoundEffect(s->sound);
if (s->flags & 0xa0)
sparkEffectDefensive(_activeSpellCaster);
else if (s->flags & 0x40)
sparkEffectDefensive(-1);
else if (s->flags & 0x1000)
sparkEffectOffensive();
if (s->flags & 0x20) {
_txt->printMessage(c->name);
_txt->printMessage(_magicStrings1[5]);
}
if ((s->flags & 0x30) && (s->effectFlags & c->effectFlags)) {
_txt->printMessage(_magicStrings7[0], -1, c->name, s->name);
snd_playSoundEffect(79);
} else if ((s->flags & 0x50) && (s->effectFlags & _partyEffectFlags)) {
_txt->printMessage(_magicStrings7[1], -1, s->name);
snd_playSoundEffect(79);
} else {
if (s->flags & 8)
setSpellEventTimer(spell, s->timingPara[0], s->timingPara[1], s->timingPara[2], s->timingPara[3]);
_returnAfterSpellCallback = false;
if (s->startCallback)
(this->*s->startCallback)();
if (_returnAfterSpellCallback)
return;
if (s->flags & 1)
c->effectFlags |= s->effectFlags;
if (s->flags & 4)
_partyEffectFlags |= s->effectFlags;
if (s->flags & 0x200) {
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
if (!testCharacter(i, 2) && !(s->flags & 0x800))
continue;
_characters[i].effectFlags |= s->effectFlags;
}
}
if (s->flags & 2)
recalcArmorClass(_activeSpellCaster);
if (s->flags & 0x20A0)
gui_drawCharPortraitWithStats(_activeSpellCaster);
if (s->flags & 0x40)
gui_drawAllCharPortraitsWithStats();
}
if (_castScrollSlot) {
gui_updateSlotAfterScrollUse();
} else {
c->disabledSlots |= 4;
setCharEventTimer(_openBookChar, 72, 11, 1);
gui_toggleButtons();
gui_drawSpellbook();
}
if (_flags.gameID == GI_EOB2) {
//_castSpellWd1 = spell;
runLevelScript(_currentBlock, 0x800);
//_castSpellWd1 = 0;
}
}
void EobCoreEngine::sparkEffectDefensive(int charIndex) {
int first = charIndex;
int last = charIndex;
if (charIndex == -1) {
first = 0;
last = 5;
}
for (int i = 0; i < 8; i++) {
for (int ii = first; ii <= last; ii++) {
if (!testCharacter(ii, 1) || (_currentControlMode && ii != _updateCharNum))
continue;
gui_drawCharPortraitWithStats(ii);
for (int iii = 0; iii < 4; iii++) {
int shpIndex = ((_sparkEffectDefSteps[i] & _sparkEffectDefSubSteps[iii]) >> _sparkEffectDefShift[iii]);
if (!shpIndex)
continue;
int x = _sparkEffectDefAdd[iii * 2] - 8;
int y = _sparkEffectDefAdd[iii * 2 + 1];
if (_currentControlMode) {
x += 181;
y += 3;
} else {
x += (_sparkEffectDefX[ii] << 3);
y += _sparkEffectDefY[ii];
}
_screen->drawShape(0, _sparkShapes[shpIndex - 1], x, y, 0);
_screen->updateScreen();
}
}
resetSkipFlag();
delay(2 * _tickLength);
}
for (int i = first; i < last; i++)
gui_drawCharPortraitWithStats(i);
}
void EobCoreEngine::sparkEffectOffensive() {
disableSysTimer(2);
_screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 2, Screen::CR_NO_P_CHECK);
for (int i = 0; i < 16; i++)
_screen->copyRegionToBuffer(0, _sparkEffectOfX[i], _sparkEffectOfY[i], 16, 16, &_spellAnimBuffer[i << 8]);
_screen->updateScreen();
for (int i = 0; i < 11; i++) {
for (int ii = 0; ii < 16; ii++)
_screen->copyBlockToPage(2, _sparkEffectOfX[ii], _sparkEffectOfY[ii], 16, 16, &_spellAnimBuffer[ii << 8]);
for (int ii = 0; ii < 16; ii++) {
int shpIndex = (_sparkEffectOfFlags1[i] & _sparkEffectOfFlags2[ii]) >> _sparkEffectOfShift[ii];
if (shpIndex)
_screen->drawShape(2, _sparkShapes[shpIndex - 1], _sparkEffectOfX[ii], _sparkEffectOfY[ii], 0);
}
resetSkipFlag();
delay(2 * _tickLength);
_screen->copyRegion(0, 0, 0, 0, 176, 120, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
}
for (int i = 0; i < 16; i++)
_screen->copyBlockToPage(0, _sparkEffectOfX[i], _sparkEffectOfY[i], 16, 16, &_spellAnimBuffer[i << 8]);
_screen->updateScreen();
enableSysTimer(2);
}
void EobCoreEngine::setSpellEventTimer(int spell, int timerBaseFactor, int timerLength, int timerLevelFactor, int updateExistingTimer) {
int l = _openBookType == 1 ? getCharacterClericPaladinLevel(_openBookChar) : getCharacterMageLevel(_openBookChar);
uint32 countdown = timerLength * timerBaseFactor + timerLength * l * timerLevelFactor;
setCharEventTimer(_activeSpellCaster, countdown, -spell, updateExistingTimer);
}
bool EobCoreEngine::magicObjectHit(EobFlyingObject *fo, int dcTimes, int dcPips, int dcOffs, int level) {
int ignoreAttackerId = fo->flags & 0x10;
int singleTargetCheckAdjacent = fo->flags & 1;
int blockDamage = fo->flags & 2;
int hitTest = fo->flags & 4;
int s = 5;
int dmgType = 3;
if (fo->flags & 8) {
s = 4;
dmgType = 0;
}
int dmgFlag = _spells[fo->callBackIndex].damageFlags;
if (fo->attackerId >= 0)
dmgFlag |= 0x800;
bool res = false;
if (!level)
level = 1;
if ((_levelBlockProperties[fo->curBlock].flags & 7) && (fo->attackerId >= 0 || ignoreAttackerId)) {
_inflictMonsterDamageUnk = 1;
for (const int16 *m = findBlockMonsters(fo->curBlock, fo->curPos, fo->direction, blockDamage, singleTargetCheckAdjacent); *m != -1; m++) {
int dmg = rollDice(dcTimes, dcPips, dcOffs) * level;
if (hitTest) {
if (!characterAttackHitTest(fo->attackerId, *m, 0, 0))
continue;
}
calcAndInflictMonsterDamage(&_monsters[*m], 0, 0, dmg, dmgFlag, s, dmgType);
res = true;
}
updateAllMonsterShapes();
} else if (fo->curBlock == _currentBlock && (fo->attackerId < 0 || ignoreAttackerId)) {
if (blockDamage) {
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 1))
continue;
if (hitTest && !monsterAttackHitTest(&_monsters[0], i))
continue;
int dmg = rollDice(dcTimes, dcPips, dcOffs) * level;
res = true;
calcAndInflictCharacterDamage(i, 0, 0, dmg, dmgFlag, s, dmgType);
}
} else {
int c = _dscItemPosIndex[(_currentDirection << 2) + (fo->curPos & 3)];
if ((c > 2) && (testCharacter(5, 1) || testCharacter(6, 1)) && rollDice(1, 2, -1))
c += 2;
if (!fo->item && (_characters[c].effectFlags & 8)) {
res = true;
} else {
if ((_characters[c].flags & 1) && hitTest && !monsterAttackHitTest(&_monsters[0], c)) {
int dmg = rollDice(dcTimes, dcPips, dcOffs) * level;
res = true;
calcAndInflictCharacterDamage(c, 0, 0, dmg, dmgFlag, s, dmgType);
}
}
}
}
if (res && (fo->flags & 0x40))
updateFlyingObject_s3(fo);
else if ((_flags.gameID == GI_EOB1 && fo->item == 5) || (_flags.gameID == GI_EOB2 && fo->item == 4))
res = false;
return res;
}
void EobCoreEngine::spellCallback_start_armor() {
}
void EobCoreEngine::spellCallback_start_burningHands() {
}
void EobCoreEngine::spellCallback_start_detectMagic() {
}
bool EobCoreEngine::spellCallback_end_detectMagic(EobFlyingObject*) {
return true;
}
void EobCoreEngine::spellCallback_start_magicMissile() {
launchMagicObject(_openBookChar, 0, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_magicMissile(EobFlyingObject *fo) {
return magicObjectHit(fo, 1, 4, 1, (getCharacterMageLevel(fo->attackerId) - 1) >> 1);
}
void EobCoreEngine::spellCallback_start_shockingGrasp() {
}
bool EobCoreEngine::spellCallback_end_shockingGraspFlameBlade(EobFlyingObject*) {
return true;
}
void EobCoreEngine::spellCallback_start_improvedIdentify() {
}
void EobCoreEngine::spellCallback_start_melfsAcidArrow() {
launchMagicObject(_openBookChar, 1, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_melfsAcidArrow(EobFlyingObject *fo) {
return magicObjectHit(fo, 2, 4, 0, getCharacterMageLevel(fo->attackerId) / 3);
}
void EobCoreEngine::spellCallback_start_dispelMagic() {
}
void EobCoreEngine::spellCallback_start_fireball() {
launchMagicObject(_openBookChar, 2, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_fireball(EobFlyingObject *fo) {
return magicObjectHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId));
}
void EobCoreEngine::spellCallback_start_flameArrow() {
launchMagicObject(_openBookChar, 3, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_flameArrow(EobFlyingObject *fo) {
return magicObjectHit(fo, 5, 6, 0, getCharacterMageLevel(fo->attackerId));
}
void EobCoreEngine::spellCallback_start_holdPerson() {
launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 4 : 3, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_holdPerson(EobFlyingObject *fo) {
return true;
}
void EobCoreEngine::spellCallback_start_lightningBolt() {
launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 5 : 4, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_lightningBolt(EobFlyingObject *fo) {
return magicObjectHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId));
}
void EobCoreEngine::spellCallback_start_vampiricTouch() {
}
bool EobCoreEngine::spellCallback_end_vampiricTouch(EobFlyingObject*) {
return true;
}
void EobCoreEngine::spellCallback_start_fear() {
}
void EobCoreEngine::spellCallback_start_iceStorm() {
launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 6 : 5, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_iceStorm(EobFlyingObject *fo) {
static int8 blockAdv[] = { -32, 32, 1, -1 };
bool res = magicObjectHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId));
if (res) {
for (int i = 0; i < 4; i++) {
uint16 bl = fo->curBlock;
fo->curBlock = (fo->curBlock + blockAdv[i]) & 0x3ff;
magicObjectHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId));
fo->curBlock = bl;
}
}
return res;
}
void EobCoreEngine::spellCallback_start_removeCurse() {
}
void EobCoreEngine::spellCallback_start_coneOfCold() {
}
void EobCoreEngine::spellCallback_start_holdMonster() {
}
bool EobCoreEngine::spellCallback_end_holdMonster(EobFlyingObject *fo) {
return true;
}
void EobCoreEngine::spellCallback_start_wallOfForce() {
}
void EobCoreEngine::spellCallback_start_disintegrate() {
}
void EobCoreEngine::spellCallback_start_fleshToStone() {
}
void EobCoreEngine::spellCallback_start_stoneToFlesh() {
}
void EobCoreEngine::spellCallback_start_trueSeeing() {
}
bool EobCoreEngine::spellCallback_end_trueSeeing(EobFlyingObject*) {
return true;
}
void EobCoreEngine::spellCallback_start_slayLiving() {
}
void EobCoreEngine::spellCallback_start_powerWordStun() {
}
void EobCoreEngine::spellCallback_start_causeLightWounds() {
}
void EobCoreEngine::spellCallback_start_cureLightWounds() {
modifyCharacterHitpoints(_activeSpellCaster, rollDice(1, 8));
}
void EobCoreEngine::spellCallback_start_aid() {
}
bool EobCoreEngine::spellCallback_end_aid(EobFlyingObject*) {
return true;
}
void EobCoreEngine::spellCallback_start_flameBlade() {
}
void EobCoreEngine::spellCallback_start_slowPoison() {
}
bool EobCoreEngine::spellCallback_end_slowPoison(EobFlyingObject*) {
return true;
}
void EobCoreEngine::spellCallback_start_createFood() {
for (int i = 0; i < 6; i++) {
if (!testCharacter(i, 3))
continue;
_characters[_activeSpellCaster].food = 100;
}
}
void EobCoreEngine::spellCallback_start_removeParalysis() {
}
void EobCoreEngine::spellCallback_start_causeSeriousWounds() {
modifyCharacterHitpoints(_activeSpellCaster, rollDice(2, 8, 1));
}
void EobCoreEngine::spellCallback_start_cureSeriousWounds() {
}
void EobCoreEngine::spellCallback_start_neutralizePoison() {
}
void EobCoreEngine::spellCallback_start_causeCriticalWounds() {
}
void EobCoreEngine::spellCallback_start_cureCriticalWounds() {
modifyCharacterHitpoints(_activeSpellCaster, rollDice(3, 8, 3));
}
void EobCoreEngine::spellCallback_start_flameStrike() {
launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 8 : 7, _currentBlock, _activeSpellCasterPos, _currentDirection);
}
bool EobCoreEngine::spellCallback_end_flameStrike(EobFlyingObject *fo) {
return magicObjectHit(fo, 6, 8, 0, 0);
}
void EobCoreEngine::spellCallback_start_raiseDead() {
}
void EobCoreEngine::spellCallback_start_harm() {
}
void EobCoreEngine::spellCallback_start_heal() {
EobCharacter *c = &_characters[_activeSpellCaster];
if (c->hitPointsMax <= c->hitPointsCur) {
_txt->printMessage(_magicStrings4[0]);
snd_playSoundEffect(79);
} else {
modifyCharacterHitpoints(_activeSpellCaster, c->hitPointsMax - c->hitPointsCur);
}
}
void EobCoreEngine::spellCallback_start_layOnHands() {
}
void EobCoreEngine::spellCallback_start_turnUndead() {
}
bool EobCoreEngine::spellCallback_end_unk1Passive(EobFlyingObject *fo) {
bool res = false;
if (_partyEffectFlags & 0x20000) {
res = magicObjectHit(fo, 4, 10, 6, 0);
if (res) {
gui_drawAllCharPortraitsWithStats();
_partyEffectFlags &= ~0x20000;
}
} else {
res = magicObjectHit(fo, 12, 10, 6, 0);
}
return res;
}
bool EobCoreEngine::spellCallback_end_unk2Passive(EobFlyingObject *fo) {
return magicObjectHit(fo, 0, 0, 18, 0);
}
bool EobCoreEngine::spellCallback_end_deathSpellPassive(EobFlyingObject *fo) {
return true;
}
bool EobCoreEngine::spellCallback_end_disintegratePassive(EobFlyingObject *fo) {
return true;
}
bool EobCoreEngine::spellCallback_end_causeCriticalWoundsPassive(EobFlyingObject *fo) {
return true;
}
bool EobCoreEngine::spellCallback_end_fleshToStonePassive(EobFlyingObject *fo) {
return true;
}
} // End of namespace Kyra
#endif // ENABLE_EOB

View File

@ -72,8 +72,19 @@ MODULE_OBJS := \
vqa.o \
wsamovie.o
KYRARPG_COMMON_OBJ = \
gui_eob.o \
loleobbase.o \
saveload_eob.o \
scene_eob.o \
sprites_eob.o \
staticres_eob.o \
text_eob.o \
timer_eob.o
ifdef ENABLE_LOL
MODULE_OBJS += \
$(KYRARPG_COMMON_OBJ) \
gui_lol.o \
items_lol.o \
lol.o \
@ -89,6 +100,24 @@ MODULE_OBJS += \
timer_lol.o
endif
ifdef ENABLE_EOB
ifndef ENABLE_LOL
MODULE_OBJS += \
$(KYRARPG_COMMON_OBJ)
endif
MODULE_OBJS += \
chargen.o \
eobcommon.o \
eob1.o \
eob2.o \
items_eob.o \
magic_eob.o \
screen_eob.o \
script_eob.o \
sequences_eob1.o \
sequences_eob2.o
endif
# This module can be built as a plugin
ifeq ($(ENABLE_KYRA), DYNAMIC_PLUGIN)
PLUGIN := 1

View File

@ -59,7 +59,7 @@ bool Resource::reset() {
if (!dir.exists() || !dir.isDirectory())
error("invalid game path '%s'", dir.getPath().c_str());
if (_vm->game() == GI_KYRA1) {
if (_vm->game() == GI_KYRA1 || _vm->game() == GI_EOB1) {
// We only need kyra.dat for the demo.
if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie)
return true;
@ -128,7 +128,7 @@ bool Resource::reset() {
loadProtectedFiles(list);
}
} else {
} else if (_vm->game() != GI_EOB2) {
error("Unknown game id: %d", _vm->game());
return false; // for compilers that don't support NORETURN
}

View File

@ -35,6 +35,7 @@
#include "common/archive.h"
#include "kyra/kyra_v1.h"
#include "kyra/eob2.h"
#include "kyra/lol.h"
#include "kyra/kyra_hof.h"
@ -250,7 +251,264 @@ enum KyraResources {
k3ItemMagicTable,
k3ItemStringMap,
#ifdef ENABLE_LOL
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
kLolEobCommonMoreStrings,
kLolEobCommonDscShapeIndex,
kLolEobCommonDscX,
kLolEobCommonDscTileIndex,
kLolEobCommonDscUnk2,
kLolEobCommonDscDoorShapeIndex,
kLolEobCommonDscDimData1,
kLolEobCommonDscDimData2,
kLolEobCommonDscBlockMap,
kLolEobCommonDscDimMap,
kLolEobCommonDscDoorY2,
kLolEobCommonDscBlockIndex,
kEobBaseChargenStrings1,
kEobBaseChargenStrings2,
kEobBaseChargenStartLevels,
kEobBaseChargenStatStrings,
kEobBaseChargenRaceSexStrings,
kEobBaseChargenClassStrings,
kEobBaseChargenAlignmentStrings,
kEobBaseChargenEnterGameStrings,
kEobBaseChargenClassMinStats,
kEobBaseChargenRaceMinStats,
kEobBaseChargenRaceMaxStats,
kEobBaseConstModTable1,
kEobBaseConstModTable2,
kEobBaseConstModTable3,
kEobBaseConstModTable4,
kEobBaseConstModLvlIndex,
kEobBaseConstModDiv,
kEobBaseConstModExt,
kEobBasePryDoorStrings,
kEobBaseWarningStrings,
kEobBaseItemSuffixStrings,
kEobBaseItemExtraStrings,
kEobBaseTakenStrings,
kEobBasePotionEffectStrings,
kEobBaseYesNoStrings,
kEobBaseNpcMaxStrings,
kEobBaseOkStrings,
kEobBaseNpcJoinStrings,
kEobBaseCancelStrings,
kEobBaseAbortStrings,
kEobBaseCharGuiStringsHp,
kEobBaseCharGuiStringsWp1,
kEobBaseCharGuiStringsWp2,
kEobBaseCharGuiStringsWr,
kEobBaseCharGuiStringsSt1,
kEobBaseCharGuiStringsSt2,
kEobBaseCharGuiStringsIn,
kEobBaseCharStatusStrings7,
kEobBaseCharStatusStrings81,
kEobBaseCharStatusStrings82,
kEobBaseCharStatusStrings9,
kEobBaseCharStatusStrings12,
kEobBaseCharStatusStrings131,
kEobBaseCharStatusStrings132,
kEobBaseLevelGainStrings,
kEobBaseExperienceTable0,
kEobBaseExperienceTable1,
kEobBaseExperienceTable2,
kEobBaseExperienceTable3,
kEobBaseExperienceTable4,
kEobBaseClassModifierFlags,
kEobBaseMonsterStepTable01,
kEobBaseMonsterStepTable02,
kEobBaseMonsterStepTable1,
kEobBaseMonsterStepTable2,
kEobBaseMonsterStepTable3,
kEobBaseMonsterCloseAttPosTable1,
kEobBaseMonsterCloseAttPosTable21,
kEobBaseMonsterCloseAttPosTable22,
kEobBaseMonsterCloseAttUnkTable,
kEobBaseMonsterCloseAttChkTable1,
kEobBaseMonsterCloseAttChkTable2,
kEobBaseMonsterCloseAttDstTable1,
kEobBaseMonsterCloseAttDstTable2,
kEobBaseMonsterProximityTable,
kEobBaseFindBlockMonstersTable,
kEobBaseMonsterDirChangeTable,
kEobBaseMonsterDistAttStrings,
kEobBaseEncodeMonsterDefs,
kEobBaseNpcPresets,
kEobBaseWllFlagPreset,
kEobBaseDscShapeCoords,
kEobBaseDscDoorScaleOffs,
kEobBaseDscDoorScaleMult1,
kEobBaseDscDoorScaleMult2,
kEobBaseDscDoorScaleMult3,
kEobBaseDscDoorScaleMult4,
kEobBaseDscDoorScaleMult5,
kEobBaseDscDoorScaleMult6,
kEobBaseDscDoorType5Offs,
kEobBaseDscDoorY1,
kEobBaseDscDoorY3,
kEobBaseDscDoorY4,
kEobBaseDscDoorY5,
kEobBaseDscDoorY6,
kEobBaseDscDoorCoordsExt,
kEobBaseDscItemPosIndex,
kEobBaseDscItemShpX,
kEobBaseDscItemScaleIndex,
kEobBaseDscItemTileIndex,
kEobBaseDscItemShapeMap,
kEobBaseDscMonsterFrmOffsTbl1,
kEobBaseDscMonsterFrmOffsTbl2,
kEobBaseInvSlotX,
kEobBaseInvSlotY,
kEobBaseSlotValidationFlags,
kEobBaseDrawObjPosIndex,
kEobBaseFlightObjFlipIndex,
kEobBaseFlightObjShpMap,
kEobBaseFlightObjSclIndex,
kEobBaseDscTelptrShpCoords,
kEobBaseBookNumbers,
kEobBaseMageSpellsList,
kEobBaseClericSpellsList,
kEobBaseSpellNames,
kEobBaseMagicStrings1,
kEobBaseMagicStrings2,
kEobBaseMagicStrings3,
kEobBaseMagicStrings4,
kEobBaseMagicStrings5,
kEobBaseMagicStrings6,
kEobBaseMagicStrings7,
kEobBaseMagicStrings8,
kEobBaseSparkDefSteps,
kEobBaseSparkDefSubSteps,
kEobBaseSparkDefShift,
kEobBaseSparkDefAdd,
kEobBaseSparkDefX,
kEobBaseSparkDefY,
kEobBaseSparkOfFlags1,
kEobBaseSparkOfFlags2,
kEobBaseSparkOfShift,
kEobBaseSparkOfX,
kEobBaseSparkOfY,
kEobBaseSpellProperties,
kEobBaseMagicFlightProps,
kEob1MainMenuStrings,
kEob1DoorShapeDefs,
kEob1DoorSwitchShapeDefs,
kEob1DoorSwitchCoords,
kEob1MonsterProperties,
kEob1MonsterDistAttType10,
kEob1MonsterDistAttSfx10,
kEob1MonsterDistAttType17,
kEob1MonsterDistAttSfx17,
kEob2MainMenuStrings,
kEob2IntroStrings,
kEob2IntroCPSFiles,
kEob2IntroSeqData00,
kEob2IntroSeqData01,
kEob2IntroSeqData02,
kEob2IntroSeqData03,
kEob2IntroSeqData04,
kEob2IntroSeqData05,
kEob2IntroSeqData06,
kEob2IntroSeqData07,
kEob2IntroSeqData08,
kEob2IntroSeqData09,
kEob2IntroSeqData10,
kEob2IntroSeqData11,
kEob2IntroSeqData12,
kEob2IntroSeqData13,
kEob2IntroSeqData14,
kEob2IntroSeqData15,
kEob2IntroSeqData16,
kEob2IntroSeqData17,
kEob2IntroSeqData18,
kEob2IntroSeqData19,
kEob2IntroSeqData20,
kEob2IntroSeqData21,
kEob2IntroSeqData22,
kEob2IntroSeqData23,
kEob2IntroSeqData24,
kEob2IntroSeqData25,
kEob2IntroSeqData26,
kEob2IntroSeqData27,
kEob2IntroSeqData28,
kEob2IntroSeqData29,
kEob2IntroSeqData30,
kEob2IntroSeqData31,
kEob2IntroSeqData32,
kEob2IntroSeqData33,
kEob2IntroSeqData34,
kEob2IntroSeqData35,
kEob2IntroSeqData36,
kEob2IntroSeqData37,
kEob2IntroSeqData38,
kEob2IntroSeqData39,
kEob2IntroSeqData40,
kEob2IntroSeqData41,
kEob2IntroSeqData42,
kEob2IntroSeqData43,
kEob2IntroShapes00,
kEob2IntroShapes01,
kEob2IntroShapes04,
kEob2IntroShapes07,
kEob2FinaleStrings,
kEob2CreditsData,
kEob2FinaleCPSFiles,
kEob2FinaleSeqData00,
kEob2FinaleSeqData01,
kEob2FinaleSeqData02,
kEob2FinaleSeqData03,
kEob2FinaleSeqData04,
kEob2FinaleSeqData05,
kEob2FinaleSeqData06,
kEob2FinaleSeqData07,
kEob2FinaleSeqData08,
kEob2FinaleSeqData09,
kEob2FinaleSeqData10,
kEob2FinaleSeqData11,
kEob2FinaleSeqData12,
kEob2FinaleSeqData13,
kEob2FinaleSeqData14,
kEob2FinaleSeqData15,
kEob2FinaleSeqData16,
kEob2FinaleSeqData17,
kEob2FinaleSeqData18,
kEob2FinaleSeqData19,
kEob2FinaleSeqData20,
kEob2FinaleShapes00,
kEob2FinaleShapes03,
kEob2FinaleShapes07,
kEob2FinaleShapes09,
kEob2FinaleShapes10,
kEob2NpcShapeData,
kEob2Npc1Strings,
kEob2Npc2Strings,
kEob2MonsterDustStrings,
kLolIngamePakFiles,
kLolCharacterDefs,
kLolIngameSfxFiles,
@ -284,27 +542,17 @@ enum KyraResources {
kLolItemPrices,
kLolStashSetup,
kLolDscUnk1,
kLolDscShapeIndex,
kLolDscWalls,
kLolDscOvlMap,
kLolDscScaleWidthData,
kLolDscScaleHeightData,
kLolDscX,
kLolDscY,
kLolDscTileIndex,
kLolDscUnk2,
kLolDscDoorShapeIndex,
kLolDscDimData1,
kLolDscDimData2,
kLolDscBlockMap,
kLolDscDimMap,
kLolDscDoor1,
kLolBaseDscY,
kLolDscDoorScale,
kLolDscDoor4,
kLolDscDoorX,
kLolDscDoorY,
kLolDscOvlIndex,
kLolDscBlockIndex,
kLolScrollXTop,
kLolScrollYTop,
@ -334,7 +582,7 @@ enum KyraResources {
kLolCredits,
kLolHistory,
#endif
#endif // ENABLE_EOB || ENABLE_LOL
kMaxResIDs
};
@ -363,15 +611,22 @@ public:
const HofSeqData *loadHofSequenceData(int id, int &entries);
const ItemAnimData_v1 *loadShapeAnimData_v1(int id, int &entries);
const ItemAnimData_v2 *loadShapeAnimData_v2(int id, int &entries);
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
const uint16 *loadRawDataBe16(int id, int &entries);
const uint32 *loadRawDataBe32(int id, int &entries);
#endif // (ENABLE_EOB || ENABLE_LOL)
#ifdef ENABLE_LOL
const LoLCharacter *loadCharData(int id, int &entries);
const SpellProperty *loadSpellData(int id, int &entries);
const CompassDef *loadCompassData(int id, int &entries);
const FlyingObjectShape *loadFlyingObjectData(int id, int &entries);
const uint16 *loadRawDataBe16(int id, int &entries);
const uint32 *loadRawDataBe32(int id, int &entries);
const ButtonDef *loadButtonDefs(int id, int &entries);
const LoLButtonDef *loadButtonDefs(int id, int &entries);
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
const EobSequenceStep *loadEob2SeqData(int id, int &entries);
const EobShapeDef *loadEob2ShapeData(int id, int &entries);
const EobCharacter *loadEobNpcData(int id, int &entries);
#endif // ENABLE_EOB
// use '-1' to prefetch/unload all ids
// prefetchId retruns false if only on of the resources
@ -398,15 +653,22 @@ private:
bool loadHofSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadShapeAnimData_v1(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadShapeAnimData_v2(Common::SeekableReadStream &stream, void *&ptr, int &size);
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
bool loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadRawDataBe32(Common::SeekableReadStream &stream, void *&ptr, int &size);
#endif // (ENABLE_LOL || ENABLE_EOB)
#ifdef ENABLE_LOL
bool loadCharData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadSpellData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadCompassData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadFlyingObjectData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadRawDataBe32(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadButtonDefs(Common::SeekableReadStream &stream, void *&ptr, int &size);
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
bool loadEob2SeqData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadEob2ShapeData(Common::SeekableReadStream &stream, void *&ptr, int &size);
bool loadEobNpcData(Common::SeekableReadStream &stream, void *&ptr, int &size);
#endif // ENABLE_EOB
void freeRawData(void *&ptr, int &size);
void freeStringTable(void *&ptr, int &size);
@ -416,15 +678,22 @@ private:
void freeHofSequenceData(void *&ptr, int &size);
void freeHofShapeAnimDataV1(void *&ptr, int &size);
void freeHofShapeAnimDataV2(void *&ptr, int &size);
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
void freeRawDataBe16(void *&ptr, int &size);
void freeRawDataBe32(void *&ptr, int &size);
#endif // (ENABLE_EOB || ENABLE_LOL)
#ifdef ENABLE_LOL
void freeCharData(void *&ptr, int &size);
void freeSpellData(void *&ptr, int &size);
void freeCompassData(void *&ptr, int &size);
void freeFlyingObjectData(void *&ptr, int &size);
void freeRawDataBe16(void *&ptr, int &size);
void freeRawDataBe32(void *&ptr, int &size);
void freeButtonDefs(void *&ptr, int &size);
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
void freeEob2SeqData(void *&ptr, int &size);
void freeEob2ShapeData(void *&ptr, int &size);
void freeEobNpcData(void *&ptr, int &size);
#endif // ENABLE_EOB
enum ResTypes {
kStringList = 0,
@ -443,7 +712,11 @@ private:
kLolFlightShpData = 11,
kLolButtonData = 12,
kLolRawDataBe16 = 13,
kLolRawDataBe32 = 14
kLolRawDataBe32 = 14,
kEob2SequenceData = 15,
kEob2ShapeData = 16,
kEobNpcData = 17
};
struct FileType {

View File

@ -254,6 +254,8 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe
offset = SWAP_BYTES_32(offset);
}
int32 firstOffset = offset;
Common::String file;
while (!stream.eos()) {
// The start offset of a file should never be in the filelist
@ -276,7 +278,7 @@ bool ResLoaderPak::isLoadable(const Common::String &filename, Common::SeekableRe
firstFile = false;
offset = switchEndian ? stream.readUint32BE() : stream.readUint32LE();
if (!offset || offset == filesize)
if (!offset || offset == filesize || firstOffset == stream.pos())
break;
}
@ -297,6 +299,7 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
bool firstFile = true;
startoffset = stream.readUint32LE();
int32 firstOffset = startoffset;
if (startoffset > filesize || startoffset < 0) {
switchEndian = true;
startoffset = SWAP_BYTES_32(startoffset);
@ -330,12 +333,12 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
firstFile = false;
endoffset = switchEndian ? stream.readUint32BE() : stream.readUint32LE();
if (endoffset < 0) {
if (endoffset < 0 && stream.pos() != firstOffset) {
warning("PAK file '%s' is corrupted", memberFile->getDisplayName().c_str());
return 0;
}
if (!endoffset)
if (!endoffset || stream.pos() == firstOffset)
endoffset = filesize;
if (startoffset != endoffset)
@ -493,7 +496,7 @@ public:
void advSrcBitsBy1();
void advSrcBitsByIndex(uint8 newIndex);
uint8 getKeyLower() { return _key & 0xff; }
uint8 getKeyLower() const { return _key & 0xff; }
void setIndex(uint8 index) { _index = index; }
uint16 getKeyMasked(uint8 newIndex);
uint16 keyMaskedAlign(uint16 val);

View File

@ -0,0 +1,549 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/eobcommon.h"
#include "kyra/resource.h"
#include "kyra/script_eob.h"
#include "common/system.h"
#include "common/savefile.h"
#include "common/substream.h"
namespace Kyra {
void LolEobBaseEngine::generateTempData() {
int l = _currentLevel - 1;
if (_lvlTempData[l]) {
delete[] _lvlTempData[l]->wallsXorData;
delete[] _lvlTempData[l]->flags;
releaseMonsterTempData(_lvlTempData[l]);
releaseFlyingObjectTempData(_lvlTempData[l]);
delete _lvlTempData[l];
}
_lvlTempData[l] = new LevelTempData;
_lvlTempData[l]->wallsXorData = new uint8[4096];
_lvlTempData[l]->flags = new uint16[1024];
char filename[13];
const uint8 *p = 0;
const uint8 *p2 = 0;
if (_flags.gameID == GI_LOL) {
snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", _currentLevel);
screen()->loadBitmap(filename, 15, 15, 0);
p = screen()->getCPagePtr(14);
} else {
snprintf(filename, sizeof(filename), "LEVEL%d.MAZ", _currentLevel);
p2 = p = _res->fileData(filename, 0);
}
uint16 len = READ_LE_UINT16(p + 4);
p += 6;
memset(_lvlTempData[l]->wallsXorData, 0, 4096);
memset(_lvlTempData[l]->flags, 0, 1024 * sizeof(uint16));
uint8 *d = _lvlTempData[l]->wallsXorData;
uint16 *df = _lvlTempData[l]->flags;
for (int i = 0; i < 1024; i++) {
for (int ii = 0; ii < 4; ii++)
*d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
*df++ = _levelBlockProperties[i].flags;
}
_lvlTempData[l]->monsters = generateMonsterTempData(_lvlTempData[l]);
_lvlTempData[l]->flyingObjects = generateFlyingObjectTempData(_lvlTempData[l]);
_hasTempDataFlags |= (1 << l);
delete[] p2;
}
void LolEobBaseEngine::restoreBlockTempData(int levelIndex) {
int l = levelIndex - 1;
char filename[13];
const uint8 *p = 0;
const uint8 *p2 = 0;
if (_flags.gameID == GI_LOL) {
snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", levelIndex);
screen()->loadBitmap(filename, 3, 3, 0);
p = screen()->getCPagePtr(2);
} else {
snprintf(filename, sizeof(filename), "LEVEL%d.MAZ", levelIndex);
p2 = p = _res->fileData(filename, 0);
}
uint16 len = READ_LE_UINT16(p + 4);
p += 6;
memset(_levelBlockProperties, 0, 1024 * sizeof(LevelBlockProperty));
uint8 *t = _lvlTempData[l]->wallsXorData;
uint16 *t2 = _lvlTempData[l]->flags;
for (int i = 0; i < 1024; i++) {
for (int ii = 0; ii < 4; ii++)
_levelBlockProperties[i].walls[ii] = p[i * len + ii] ^ *t++;
_levelBlockProperties[i].flags = *t2++;
}
restoreMonsterTempData(_lvlTempData[l]);
restoreFlyingObjectTempData(_lvlTempData[l]);
delete[] p2;
}
void LolEobBaseEngine::releaseTempData() {
for (int i = 0; i < 29; i++) {
if (_lvlTempData[i]) {
delete[] _lvlTempData[i]->wallsXorData;
delete[] _lvlTempData[i]->flags;
releaseMonsterTempData(_lvlTempData[i]);
releaseFlyingObjectTempData(_lvlTempData[i]);
delete _lvlTempData[i];
_lvlTempData[i] = 0;
}
}
}
#ifdef ENABLE_EOB
Common::Error EobCoreEngine::loadGameState(int slot) {
const char *fileName = getSavegameFilename(slot);
SaveHeader header;
Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
if (!saveFile) {
//_txt->printMessage(2, "%s", getLangString(0x425d));
return Common::kNoError;
}
Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES);
for (int i = 0; i < 6; i++) {
EobCharacter *c = &_characters[i];
c->id = in.readByte();
c->flags = in.readByte();
in.read(c->name, 11);
c->strengthCur = in.readSByte();
c->strengthMax = in.readSByte();
c->strengthExtCur = in.readSByte();
c->strengthExtMax = in.readSByte();
c->intelligenceCur = in.readSByte();
c->intelligenceMax = in.readSByte();
c->wisdomCur = in.readSByte();
c->wisdomMax = in.readSByte();
c->dexterityCur = in.readSByte();
c->dexterityMax = in.readSByte();
c->constitutionCur = in.readSByte();
c->constitutionMax = in.readSByte();
c->charismaCur = in.readSByte();
c->charismaMax = in.readSByte();
c->hitPointsCur = in.readSint16BE();
c->hitPointsMax = in.readSint16BE();
c->armorClass = in.readSByte();
c->disabledSlots = in.readByte();
c->raceSex = in.readByte();
c->cClass = in.readByte();
c->alignment = in.readByte();
c->portrait = in.readSByte();
c->food = in.readByte();
in.read(c->level, 3);
for (int ii = 0; ii < 3; ii++)
c->experience[ii] = in.readUint32BE();
delete[] c->faceShape;
c->faceShape = 0;
in.read(c->mageSpells, 80);
in.read(c->clericSpells, 80);
c->mageSpellsAvailabilityFlags = in.readUint32BE();
for (int ii = 0; ii < 27; ii++)
c->inventory[ii] = in.readSint16BE();
uint32 ct = _system->getMillis();
for (int ii = 0; ii < 10; ii++) {
c->timers[ii] = in.readUint32BE();
if (c->timers[ii])
c->timers[ii] += ct;
}
in.read(c->events, 10);
in.read(c->effectsRemainder, 4);
c->effectFlags = in.readUint32BE();
c->damageTaken = in.readByte();
in.read(c->slotStatus, 5);
}
setupCharacterTimers();
_screen->loadEobBitmap("CHARGENA", 3, 3);
for (int i = 0; i < 6; i++) {
EobCharacter *c = &_characters[i];
if (!c->flags || c->portrait < 0)
continue;
c->faceShape = _screen->encodeShape((c->portrait % 10) << 2, (c->portrait / 10) << 5, 4, 32, true);
}
_screen->loadEobBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3);
for (int i = 0; i < 6; i++) {
EobCharacter *c = &_characters[i];
if (!c->flags || c->portrait >= 0)
continue;
c->faceShape = _screen->encodeShape(-(c->portrait + 1), _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true);
}
_screen->_curPage = 0;
_currentLevel = in.readByte();
_currentSub = in.readSByte();
_currentBlock = in.readUint16BE();
_currentDirection = in.readUint16BE();
_itemInHand = in.readSint16BE();
_hasTempDataFlags = in.readUint32BE();
_partyEffectFlags = in.readUint32BE();
_inf->loadState(in);
for (int i = 0; i < 600; i++) {
EobItem *t = &_items[i];
t->nameUnid = in.readByte();
t->nameId = in.readByte();
t->flags = in.readByte();
t->icon = in.readSByte();
t->type = in.readSByte();
t->pos = in.readSByte();
t->block = in.readSint16BE();
t->next = in.readSint16BE();
t->prev = in.readSint16BE();
t->level = in.readByte();
t->value = in.readSByte();
}
for (int i = 51; i < 65; i++) {
EobItemType *t = &_itemTypes[i];
t->invFlags = in.readUint16BE();
t->handFlags = in.readUint16BE();
t->armorClass = in.readSByte();
t->allowedClasses = in.readSByte();
t->requiredHands = in.readSByte();
t->dmgNumDiceS = in.readSByte();
t->dmgNumPipsS = in.readSByte();
t->dmgIncS = in.readSByte();
t->dmgNumDiceL = in.readSByte();
t->dmgNumPipsL = in.readSByte();
t->dmgIncL = in.readSByte();
t->unk1 = in.readByte();
t->extraProperties = in.readUint16BE();
}
for (int i = 0; i < 18; i++) {
if (!(_hasTempDataFlags & (1 << i)))
continue;
if (_lvlTempData[i]) {
delete[] _lvlTempData[i]->wallsXorData;
delete[] _lvlTempData[i]->flags;
releaseMonsterTempData(_lvlTempData[i]);
releaseFlyingObjectTempData(_lvlTempData[i]);
delete _lvlTempData[i];
}
_lvlTempData[i] = new LevelTempData;
_lvlTempData[i]->wallsXorData = new uint8[4096];
_lvlTempData[i]->flags = new uint16[1024];
EobMonsterInPlay *lm = new EobMonsterInPlay[30];
_lvlTempData[i]->monsters = lm;
EobFlyingObject *lf = new EobFlyingObject[10];
_lvlTempData[i]->flyingObjects = lf;
LevelTempData *l = _lvlTempData[i];
in.read(l->wallsXorData, 4096);
for (int ii = 0; ii < 1024; ii++)
l->flags[ii] = in.readByte();
for (int ii = 0; ii < 30; ii++) {
EobMonsterInPlay *m = &lm[ii];
m->type = in.readByte();
m->unit = in.readByte();
m->block = in.readUint16BE();
m->pos = in.readByte();
m->dir = in.readSByte();
m->animStep = in.readByte();
m->shpIndex = in.readByte();
m->mode = in.readSByte();
m->f_9 = in.readSByte();
m->curAttackFrame = in.readSByte();
m->f_b = in.readByte();
m->hitPointsMax = in.readSint16BE();
m->hitPointsCur = in.readSint16BE();
m->dest = in.readUint16BE();
m->randItem = in.readUint16BE();
m->fixedItem = in.readUint16BE();
m->flags = in.readByte();
m->idleAnimState = in.readByte();
m->curRemoteWeapon = in.readByte();
m->numRemoteAttacks = in.readByte();
m->palette = in.readSByte();
m->directionChanged = in.readByte();
m->stepsTillRemoteAttack = in.readByte();
m->sub = in.readByte();
}
for (int ii = 0; ii < 10; ii++) {
EobFlyingObject *m = &lf[ii];
m->enable = in.readByte();
m->objectType = in.readByte();
m->attackerId = in.readSint16BE();
m->item = in.readSint16BE();
m->curBlock = in.readUint16BE();
m->u2 = in.readUint16BE();
m->u1 = in.readByte();
m->direction = in.readByte();
m->distance = in.readByte();
m->callBackIndex = in.readSByte();
m->curPos = in.readByte();
m->flags = in.readByte();
m->unused = in.readByte();
}
}
if (_saveLoadMode != -1) {
loadLevel(_currentLevel, _currentSub);
gui_drawPlayField(0);
_sceneUpdateRequired = true;
_screen->setCurPage(0);
_screen->setFont(Screen::FID_6_FNT);
gui_drawAllCharPortraitsWithStats();
updateHandItemCursor();
_saveLoadMode = 1;
}
while (!_screen->isMouseVisible())
_screen->showMouse();
return Common::kNoError;
}
Common::Error EobCoreEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) {
const Common::String finSuffix(".FIN");
const char *fileName = (slot != -1) ? getSavegameFilename(slot) : (_targetName + finSuffix).c_str();
Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail);
if (!out)
return _saveFileMan->getError();
completeDoorOperations();
generateTempData();
for (int i = 0; i < 6; i++) {
timerSpecialCharacterUpdate(0x30 + i);
uint32 ct = _system->getMillis();
EobCharacter *c = &_characters[i];
out->writeByte(c->id);
out->writeByte(c->flags);
out->write(c->name, 11);
out->writeSByte(c->strengthCur);
out->writeSByte(c->strengthMax);
out->writeSByte(c->strengthExtCur);
out->writeSByte(c->strengthExtMax);
out->writeSByte(c->intelligenceCur);
out->writeSByte(c->intelligenceMax);
out->writeSByte(c->wisdomCur);
out->writeSByte(c->wisdomMax);
out->writeSByte(c->dexterityCur);
out->writeSByte(c->dexterityMax);
out->writeSByte(c->constitutionCur);
out->writeSByte(c->constitutionMax);
out->writeSByte(c->charismaCur);
out->writeSByte(c->charismaMax);
out->writeSint16BE(c->hitPointsCur);
out->writeSint16BE(c->hitPointsMax);
out->writeSByte(c->armorClass);
out->writeByte(c->disabledSlots);
out->writeByte(c->raceSex);
out->writeByte(c->cClass);
out->writeByte(c->alignment);
out->writeByte(c->portrait);
out->writeByte(c->food);
out->write(c->level, 3);
for (int ii = 0; ii < 3; ii++)
out->writeUint32BE(c->experience[ii]);
out->write(c->mageSpells, 80);
out->write(c->clericSpells, 80);
out->writeUint32BE(c->mageSpellsAvailabilityFlags);
for (int ii = 0; ii < 27; ii++)
out->writeSint16BE(c->inventory[ii]);
for (int ii = 0; ii < 10; ii++)
out->writeUint32BE(c->timers[ii] ? c->timers[ii] - ct : 0);
out->write(c->events, 10);
out->write(c->effectsRemainder, 4);
out->writeUint32BE(c->effectFlags);
out->writeByte(c->damageTaken);
out->write(c->slotStatus, 5);
}
out->writeByte(_currentLevel);
out->writeSByte(_currentSub);
out->writeUint16BE(_currentBlock);
out->writeUint16BE(_currentDirection);
out->writeSint16BE(_itemInHand);
out->writeUint32BE(_hasTempDataFlags);
out->writeUint32BE(_partyEffectFlags);
_inf->saveState(out);
for (int i = 0; i < 600; i++) {
EobItem *t = &_items[i];
out->writeByte(t->nameUnid);
out->writeByte(t->nameId);
out->writeByte(t->flags);
out->writeSByte(t->icon);
out->writeSByte(t->type);
out->writeSByte(t->pos);
out->writeSint16BE(t->block);
out->writeSint16BE(t->next);
out->writeSint16BE(t->prev);
out->writeByte(t->level);
out->writeSByte(t->value);
}
for (int i = 51; i < 65; i++) {
EobItemType *t = &_itemTypes[i];
out->writeUint16BE(t->invFlags);
out->writeUint16BE(t->handFlags);
out->writeSByte(t->armorClass);
out->writeSByte(t->allowedClasses);
out->writeSByte(t->requiredHands);
out->writeSByte(t->dmgNumDiceS);
out->writeSByte(t->dmgNumPipsS);
out->writeSByte(t->dmgIncS);
out->writeSByte(t->dmgNumDiceL);
out->writeSByte(t->dmgNumPipsL);
out->writeSByte(t->dmgIncL);
out->writeByte(t->unk1);
out->writeUint16BE(t->extraProperties);
}
for (int i = 0; i < 18; i++) {
LevelTempData *l = _lvlTempData[i];
if (!l || !(_hasTempDataFlags & (1 << i)))
continue;
out->write(l->wallsXorData, 4096);
for (int ii = 0; ii < 1024; ii++)
out->writeByte(l->flags[ii] & 0xff);
EobMonsterInPlay *lm = (EobMonsterInPlay*)_lvlTempData[i]->monsters;
EobFlyingObject *lf = (EobFlyingObject*)_lvlTempData[i]->flyingObjects;
for (int ii = 0; ii < 30; ii++) {
EobMonsterInPlay *m = &lm[ii];
out->writeByte(m->type);
out->writeByte(m->unit);
out->writeUint16BE(m->block);
out->writeByte(m->pos);
out->writeSByte(m->dir);
out->writeByte(m->animStep);
out->writeByte(m->shpIndex);
out->writeSByte(m->mode);
out->writeSByte(m->f_9);
out->writeSByte(m->curAttackFrame);
out->writeByte(m->f_b);
out->writeSint16BE(m->hitPointsMax);
out->writeSint16BE(m->hitPointsCur);
out->writeUint16BE(m->dest);
out->writeUint16BE(m->randItem);
out->writeUint16BE(m->fixedItem);
out->writeByte(m->flags);
out->writeByte(m->idleAnimState);
out->writeByte(m->curRemoteWeapon);
out->writeByte(m->numRemoteAttacks);
out->writeSByte(m->palette);
out->writeByte(m->directionChanged);
out->writeByte(m->stepsTillRemoteAttack);
out->writeByte(m->sub);
}
for (int ii = 0; ii < 10; ii++) {
EobFlyingObject *m = &lf[ii];
out->writeByte(m->enable);
out->writeByte(m->objectType);
out->writeSint16BE(m->attackerId);
out->writeSint16BE(m->item);
out->writeUint16BE(m->curBlock);
out->writeUint16BE(m->u2);
out->writeByte(m->u1);
out->writeByte(m->direction);
out->writeByte(m->distance);
out->writeSByte(m->callBackIndex);
out->writeByte(m->curPos);
out->writeByte(m->flags);
out->writeByte(m->unused);
}
}
out->finalize();
// check for errors
if (out->err()) {
warning("Can't write file '%s'. (Disk full?)", fileName);
return Common::kUnknownError;
} else {
debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
}
delete out;
return Common::kNoError;
}
void *EobCoreEngine::generateMonsterTempData(LevelTempData *tmp) {
EobMonsterInPlay *m = new EobMonsterInPlay[30];
memcpy(m, _monsters, sizeof(EobMonsterInPlay) * 30);
return m;
}
void *EobCoreEngine::generateFlyingObjectTempData(LevelTempData *tmp) {
EobFlyingObject *f = new EobFlyingObject[10];
memcpy(f, _flyingObjects, sizeof(EobFlyingObject) * 10);
return f;
}
void EobCoreEngine::restoreMonsterTempData(LevelTempData *tmp) {
memcpy(_monsters, tmp->monsters, sizeof(EobMonsterInPlay) * 30);
}
void EobCoreEngine::restoreFlyingObjectTempData(LevelTempData *tmp) {
memcpy(_flyingObjects, tmp->flyingObjects, sizeof(EobFlyingObject) * 10);
}
void EobCoreEngine::releaseMonsterTempData(LevelTempData *tmp) {
EobMonsterInPlay *p = (EobMonsterInPlay*)tmp->monsters;
delete[] p;
}
void EobCoreEngine::releaseFlyingObjectTempData(LevelTempData *tmp) {
}
#endif // ENABLE_EOB
} // End of namespace Kyra
#endif // ENABLE_EOB || ENABLE_LOL

View File

@ -96,7 +96,7 @@ Common::Error LoLEngine::loadGameState(int slot) {
}
}
in.read(_wllBuffer4, 80);
in.read(_wllAutomapData, 80);
_currentBlock = in.readUint16BE();
_partyPosX = in.readUint16BE();
@ -185,23 +185,26 @@ Common::Error LoLEngine::loadGameState(int slot) {
if (_lvlTempData[i]) {
delete[] _lvlTempData[i]->wallsXorData;
delete[] _lvlTempData[i]->flags;
delete[] _lvlTempData[i]->monsters;
delete[] _lvlTempData[i]->flyingObjects;
releaseMonsterTempData(_lvlTempData[i]);
releaseFlyingObjectTempData(_lvlTempData[i]);
delete _lvlTempData[i];
}
_lvlTempData[i] = new LevelTempData;
_lvlTempData[i]->wallsXorData = new uint8[4096];
_lvlTempData[i]->flags = new uint8[1024];
_lvlTempData[i]->monsters = new MonsterInPlay[30];
_lvlTempData[i]->flyingObjects = new FlyingObject[8];
_lvlTempData[i]->flags = new uint16[1024];
LolMonsterInPlay *lm = new LolMonsterInPlay[30];
_lvlTempData[i]->monsters = lm;
FlyingObject *lf = new FlyingObject[8];
_lvlTempData[i]->flyingObjects = lf;
LevelTempData *l = _lvlTempData[i];
in.read(l->wallsXorData, 4096);
in.read(l->flags, 1024);
for (int ii = 0; ii < 1024; ii++)
l->flags[ii] = in.readByte();
for (int ii = 0; ii < 30; ii++) {
MonsterInPlay *m = &l->monsters[ii];
LolMonsterInPlay *m = &lm[ii];
m->nextAssignedObject = in.readUint16BE();
m->nextDrawObject = in.readUint16BE();
m->flyingHeight = in.readByte();
@ -234,7 +237,7 @@ Common::Error LoLEngine::loadGameState(int slot) {
}
for (int ii = 0; ii < 8; ii++) {
FlyingObject *m = &l->flyingObjects[ii];
FlyingObject *m = &lf[ii];
m->enable = in.readByte();
m->objectType = in.readByte();
m->attackerId = in.readUint16BE();
@ -319,7 +322,7 @@ Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, con
out->writeByte(c->characterUpdateDelay[ii]);
}
out->write(_wllBuffer4, 80);
out->write(_wllAutomapData, 80);
out->writeUint16BE(_currentBlock);
out->writeUint16BE(_partyPosX);
@ -379,10 +382,14 @@ Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, con
continue;
out->write(l->wallsXorData, 4096);
out->write(l->flags, 1024);
for (int ii = 0; ii < 1024; ii++)
out->writeByte(l->flags[ii] & 0xff);
LolMonsterInPlay *lm = (LolMonsterInPlay*)_lvlTempData[i]->monsters;
FlyingObject *lf = (FlyingObject*)_lvlTempData[i]->flyingObjects;
for (int ii = 0; ii < 30; ii++) {
MonsterInPlay *m = &l->monsters[ii];
LolMonsterInPlay *m = &lm[ii];
out->writeUint16BE(m->nextAssignedObject);
out->writeUint16BE(m->nextDrawObject);
out->writeByte(m->flyingHeight);
@ -414,7 +421,7 @@ Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, con
}
for (int ii = 0; ii < 8; ii++) {
FlyingObject *m = &l->flyingObjects[ii];
FlyingObject *m = &lf[ii];
out->writeByte(m->enable);
out->writeByte(m->objectType);
out->writeUint16BE(m->attackerId);
@ -469,6 +476,69 @@ Graphics::Surface *LoLEngine::generateSaveThumbnail() const {
return dst;
}
void LoLEngine::restoreBlockTempData(int levelIndex) {
memset(_tempBuffer5120, 0, 5120);
LolEobBaseEngine::restoreBlockTempData(levelIndex);
restoreTempDataAdjustMonsterStrength(levelIndex - 1);
}
void *LoLEngine::generateMonsterTempData(LevelTempData *tmp) {
LolMonsterInPlay *m = new LolMonsterInPlay[30];
memcpy(m, _monsters, sizeof(LolMonsterInPlay) * 30);
tmp->monsterDifficulty = _monsterDifficulty;
return m;
}
void *LoLEngine::generateFlyingObjectTempData(LevelTempData *tmp) {
FlyingObject *f = new FlyingObject[8];
memcpy(f, _flyingObjects, sizeof(FlyingObject) * 8);
return f;
}
void LoLEngine::restoreTempDataAdjustMonsterStrength(int index) {
if (_lvlTempData[index]->monsterDifficulty == _monsterDifficulty)
return;
uint16 d = (_monsterModifiers[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers[_monsterDifficulty];
for (int i = 0; i < 30; i++) {
if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0)
continue;
_monsters[i].hitPoints = (d * _monsters[i].hitPoints) >> 8;
if (_monsterDifficulty < _lvlTempData[index]->monsterDifficulty)
_monsters[i].hitPoints++;
if (_monsters[i].hitPoints == 0)
_monsters[i].hitPoints = 1;
}
}
void LoLEngine::restoreMonsterTempData(LevelTempData *tmp) {
memcpy(_monsters, tmp->monsters, sizeof(LolMonsterInPlay) * 30);
for (int i = 0; i < 30; i++) {
if (_monsters[i].block) {
_monsters[i].block = 0;
_monsters[i].properties = &_monsterProperties[_monsters[i].type];
placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y);
}
}
}
void LoLEngine::restoreFlyingObjectTempData(LevelTempData *tmp) {
memcpy(_flyingObjects, tmp->flyingObjects, sizeof(FlyingObject) * 8);
}
void LoLEngine::releaseMonsterTempData(LevelTempData *tmp) {
LolMonsterInPlay *p = (LolMonsterInPlay*)tmp->monsters;
delete[] p;
}
void LoLEngine::releaseFlyingObjectTempData(LevelTempData *tmp) {
FlyingObject *p = (FlyingObject*)tmp->flyingObjects;
delete[] p;
}
} // End of namespace Kyra
#endif // ENABLE_LOL

1350
engines/kyra/scene_eob.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,8 @@ void LoLEngine::loadLevel(int index) {
stopPortraitSpeechAnim();
for (int i = 0; i < 400; i++) {
delete[] _levelShapes[i];
_levelShapes[i] = 0;
delete[] _levelDecorationShapes[i];
_levelDecorationShapes[i] = 0;
}
_emc->unload(&_scriptData);
@ -160,7 +160,7 @@ void LoLEngine::loadLevelWallData(int index, bool mapShapes) {
if (mapShapes) {
int16 sh = (int16) READ_LE_UINT16(d);
if (sh > 0)
_wllShapeMap[c] = assignLevelShapes(sh);
_wllShapeMap[c] = assignLevelDecorationShapes(sh);
else
_wllShapeMap[c] = *d;
}
@ -169,7 +169,7 @@ void LoLEngine::loadLevelWallData(int index, bool mapShapes) {
d += 2;
_wllWallFlags[c] = *d;
d += 2;
_wllBuffer4[c] = *d;
_wllAutomapData[c] = *d;
d += 2;
}
@ -179,7 +179,7 @@ void LoLEngine::loadLevelWallData(int index, bool mapShapes) {
_lvlShpFileHandle = 0;
}
int LoLEngine::assignLevelShapes(int index) {
int LoLEngine::assignLevelDecorationShapes(int index) {
uint16 *p1 = (uint16 *)_tempBuffer5120;
uint16 *p2 = (uint16 *)(_tempBuffer5120 + 4000);
@ -187,34 +187,34 @@ int LoLEngine::assignLevelShapes(int index) {
if (r)
return r;
uint16 o = _lvlBlockIndex++;
uint16 o = _mappedDecorationsCount++;
memcpy(&_levelShapeProperties[o], &_levelFileData[index], sizeof(LevelShapeProperty));
memcpy(&_levelDecorationProperties[o], &_levelDecorationData[index], sizeof(LevelDecorationProperty));
for (int i = 0; i < 10; i++) {
uint16 t = _levelShapeProperties[o].shapeIndex[i];
uint16 t = _levelDecorationProperties[o].shapeIndex[i];
if (t == 0xffff)
continue;
uint16 pv = p1[t];
if (pv) {
_levelShapeProperties[o].shapeIndex[i] = pv;
_levelDecorationProperties[o].shapeIndex[i] = pv;
} else {
_levelShapes[_lvlShapeIndex] = getLevelShapes(t);
_levelDecorationShapes[_lvlShapeIndex] = getLevelDecorationShapes(t);
p1[t] = _lvlShapeIndex;
_levelShapeProperties[o].shapeIndex[i] = _lvlShapeIndex++;
_levelDecorationProperties[o].shapeIndex[i] = _lvlShapeIndex++;
}
}
p2[index] = o;
if (_levelShapeProperties[o].next)
_levelShapeProperties[o].next = assignLevelShapes(_levelShapeProperties[o].next);
if (_levelDecorationProperties[o].next)
_levelDecorationProperties[o].next = assignLevelDecorationShapes(_levelDecorationProperties[o].next);
return o;
}
uint8 *LoLEngine::getLevelShapes(int shapeIndex) {
if (_lvlShpNum <= shapeIndex)
uint8 *LoLEngine::getLevelDecorationShapes(int shapeIndex) {
if (_decorationCount <= shapeIndex)
return 0;
_lvlShpFileHandle->seek(shapeIndex * 4 + 2, SEEK_SET);
@ -232,60 +232,6 @@ uint8 *LoLEngine::getLevelShapes(int shapeIndex) {
return res;
}
void LoLEngine::restoreBlockTempData(int index) {
memset(_tempBuffer5120, 0, 5120);
int l = index - 1;
memcpy(_monsters, _lvlTempData[l]->monsters, sizeof(MonsterInPlay) * 30);
memcpy(_flyingObjects, _lvlTempData[l]->flyingObjects, sizeof(FlyingObject) * 8);
Common::String filename = Common::String::format("LEVEL%d.CMZ", index);
_screen->loadBitmap(filename.c_str(), 3, 3, 0);
const uint8 *p = _screen->getCPagePtr(2);
uint16 len = READ_LE_UINT16(p + 4);
p += 6;
memset(_levelBlockProperties, 0, 1024 * sizeof(LevelBlockProperty));
uint8 *t = _lvlTempData[l]->wallsXorData;
uint8 *t2 = _lvlTempData[l]->flags;
for (int i = 0; i < 1024; i++) {
for (int ii = 0; ii < 4; ii++)
_levelBlockProperties[i].walls[ii] = p[i * len + ii] ^ *t++;
_levelBlockProperties[i].flags = *t2++;
}
for (int i = 0; i < 30; i++) {
if (_monsters[i].block) {
_monsters[i].block = 0;
_monsters[i].properties = &_monsterProperties[_monsters[i].type];
placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y);
}
}
restoreTempDataAdjustMonsterStrength(l);
}
void LoLEngine::restoreTempDataAdjustMonsterStrength(int index) {
if (_lvlTempData[index]->monsterDifficulty == _monsterDifficulty)
return;
uint16 d = (_monsterModifiers[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers[_monsterDifficulty];
for (int i = 0; i < 30; i++) {
if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0)
continue;
_monsters[i].hitPoints = (d * _monsters[i].hitPoints) >> 8;
if (_monsterDifficulty < _lvlTempData[index]->monsterDifficulty)
_monsters[i].hitPoints++;
if (_monsters[i].hitPoints == 0)
_monsters[i].hitPoints = 1;
}
}
void LoLEngine::loadBlockProperties(const char *cmzFile) {
memset(_levelBlockProperties, 0, 1024 * sizeof(LevelBlockProperty));
_screen->loadBitmap(cmzFile, 2, 2, 0);
@ -299,7 +245,7 @@ void LoLEngine::loadBlockProperties(const char *cmzFile) {
_levelBlockProperties[i].direction = 5;
if (_wllBuffer4[_levelBlockProperties[i].walls[0]] == 17) {
if (_wllAutomapData[_levelBlockProperties[i].walls[0]] == 17) {
_levelBlockProperties[i].flags &= 0xef;
_levelBlockProperties[i].flags |= 0x20;
}
@ -310,15 +256,15 @@ void LoLEngine::loadLevelShpDat(const char *shpFile, const char *datFile, bool f
memset(_tempBuffer5120, 0, 5120);
_lvlShpFileHandle = _res->createReadStream(shpFile);
_lvlShpNum = _lvlShpFileHandle->readUint16LE();
_decorationCount = _lvlShpFileHandle->readUint16LE();
Common::SeekableReadStream *s = _res->createReadStream(datFile);
_levelFileDataSize = s->readUint16LE();
delete[] _levelFileData;
_levelFileData = new LevelShapeProperty[_levelFileDataSize];
for (int i = 0; i < _levelFileDataSize; i++) {
LevelShapeProperty * l = &_levelFileData[i];
_levelDecorationDataSize = s->readUint16LE();
delete[] _levelDecorationData;
_levelDecorationData = new LevelDecorationProperty[_levelDecorationDataSize];
for (int i = 0; i < _levelDecorationDataSize; i++) {
LevelDecorationProperty * l = &_levelDecorationData[i];
for (int ii = 0; ii < 10; ii++)
l->shapeIndex[ii] = s->readUint16LE();
for (int ii = 0; ii < 10; ii++)
@ -334,7 +280,7 @@ void LoLEngine::loadLevelShpDat(const char *shpFile, const char *datFile, bool f
delete s;
if (!flag) {
_lvlBlockIndex = 1;
_mappedDecorationsCount = 1;
_lvlShapeIndex = 1;
}
}
@ -515,10 +461,10 @@ void LoLEngine::resetItems(int flag) {
for (int i = 0; i < 1024; i++) {
_levelBlockProperties[i].direction = 5;
uint16 id = _levelBlockProperties[i].assignedObjects;
MonsterInPlay *r = 0;
LolMonsterInPlay *r = 0;
while (id & 0x8000) {
r = (MonsterInPlay *)findObject(id);
r = (LolMonsterInPlay *)findObject(id);
id = r->nextAssignedObject;
}
@ -537,7 +483,7 @@ void LoLEngine::resetItems(int flag) {
}
void LoLEngine::disableMonsters() {
memset(_monsters, 0, 30 * sizeof(MonsterInPlay));
memset(_monsters, 0, 30 * sizeof(LolMonsterInPlay));
for (int i = 0; i < 30; i++)
_monsters[i].mode = 0x10;
}
@ -751,11 +697,6 @@ void LoLEngine::moveParty(uint16 direction, int unk1, int unk2, int buttonShape)
updateAutoMap(_currentBlock);
}
uint16 LoLEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) {
static const int16 blockPosTable[] = { -32, 1, 32, -1 };
return (curBlock + blockPosTable[direction]) & 0x3ff;
}
uint16 LoLEngine::calcBlockIndex(uint16 x, uint16 y) {
return (((y & 0xff00) >> 3) | (x >> 8)) & 0x3ff;
}
@ -827,51 +768,6 @@ void LoLEngine::notifyBlockNotPassable(int scrollFlag) {
snd_playSoundEffect(19, -1);
}
int LoLEngine::clickedWallShape(uint16 block, uint16 direction) {
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
if (!clickedShape(v))
return 0;
snd_stopSpeech(true);
runLevelScript(block, 0x40);
return 1;
}
int LoLEngine::clickedLeverOn(uint16 block, uint16 direction) {
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
if (!clickedShape(v))
return 0;
_levelBlockProperties[block].walls[direction]++;
_sceneUpdateRequired = true;
snd_playSoundEffect(30, -1);
runLevelScript(block, 0x40);
return 1;
}
int LoLEngine::clickedLeverOff(uint16 block, uint16 direction) {
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
if (!clickedShape(v))
return 0;
_levelBlockProperties[block].walls[direction]--;
_sceneUpdateRequired = true;
snd_playSoundEffect(29, -1);
runLevelScript(block, 0x40);
return 1;
}
int LoLEngine::clickedWallOnlyScript(uint16 block) {
runLevelScript(block, 0x40);
return 1;
}
int LoLEngine::clickedDoorSwitch(uint16 block, uint16 direction) {
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
if (!clickedShape(v))
@ -903,119 +799,6 @@ int LoLEngine::clickedNiche(uint16 block, uint16 direction) {
return 1;
}
bool LoLEngine::clickedShape(int shapeIndex) {
while (shapeIndex) {
uint16 s = _levelShapeProperties[shapeIndex].shapeIndex[1];
if (s == 0xffff) {
shapeIndex = _levelShapeProperties[shapeIndex].next;
continue;
}
int w = _levelShapes[s][3];
int h = _levelShapes[s][2];
int x = _levelShapeProperties[shapeIndex].shapeX[1] + 136;
int y = _levelShapeProperties[shapeIndex].shapeY[1] + 8;
if (_levelShapeProperties[shapeIndex].flags & 1)
w <<= 1;
if (posWithinRect(_mouseX, _mouseY, x - 4, y - 4, x + w + 8, y + h + 8))
return true;
shapeIndex = _levelShapeProperties[shapeIndex].next;
}
return false;
}
void LoLEngine::processDoorSwitch(uint16 block, int openClose) {
if ((block == _currentBlock) || (_levelBlockProperties[block].assignedObjects & 0x8000))
return;
if (openClose == 0) {
for (int i = 0; i < 3; i++) {
if (_openDoorState[i].block != block)
continue;
openClose = -_openDoorState[i].state;
break;
}
}
if (openClose == 0)
openClose = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1;
openCloseDoor(block, openClose);
}
void LoLEngine::openCloseDoor(uint16 block, int openClose) {
int s1 = -1;
int s2 = -1;
int c = (_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1;
int v = _levelBlockProperties[block].walls[c];
int flg = (openClose == 1) ? 0x10 : (openClose == -1 ? 0x20 : 0);
if (_wllWallFlags[v] & flg)
return;
for (int i = 0; i < 3; i++) {
if (_openDoorState[i].block == block) {
s1 = i;
break;
} else if (_openDoorState[i].block == 0 && s2 == -1) {
s2 = i;
}
}
if (s1 != -1 || s2 != -1) {
if (s1 == -1)
s1 = s2;
_openDoorState[s1].block = block;
_openDoorState[s1].state = openClose;
_openDoorState[s1].wall = c;
flg = (-openClose == 1) ? 0x10 : (-openClose == -1 ? 0x20 : 0);
if (_wllWallFlags[v] & flg) {
_levelBlockProperties[block].walls[c] += openClose;
_levelBlockProperties[block].walls[c ^ 2] += openClose;
int snd = (openClose == -1) ? 32 : 31;
snd_processEnvironmentalSoundEffect(snd, block);
if (!checkSceneUpdateNeed(block))
updateEnvironmentalSfx(0);
}
enableTimer(0);
} else {
while (!(flg & _wllWallFlags[v]))
v += openClose;
_levelBlockProperties[block].walls[c] = _levelBlockProperties[block].walls[c ^ 2] = v;
checkSceneUpdateNeed(block);
}
}
void LoLEngine::completeDoorOperations() {
for (int i = 0; i < 3; i++) {
if (!_openDoorState[i].block)
continue;
uint16 b = _openDoorState[i].block;
do {
_levelBlockProperties[b].walls[_openDoorState[i].wall] += _openDoorState[i].state;
_levelBlockProperties[b].walls[_openDoorState[i].wall ^ 2] += _openDoorState[i].state;
} while (!(_wllWallFlags[_levelBlockProperties[b].walls[_openDoorState[i].wall]] & 0x30));
_openDoorState[i].block = 0;
}
}
void LoLEngine::movePartySmoothScrollBlocked(int speed) {
if (!_smoothScrollingEnabled || (_smoothScrollingEnabled && _needSceneRestore))
return;
@ -1447,7 +1230,7 @@ void LoLEngine::setWallType(int block, int wall, int val) {
if (wall == -1) {
for (int i = 0; i < 4; i++)
_levelBlockProperties[block].walls[i] = val;
if (_wllBuffer4[val] == 17) {
if (_wllAutomapData[val] == 17) {
_levelBlockProperties[block].flags &= 0xef;
_levelBlockProperties[block].flags |= 0x20;
} else {
@ -1603,334 +1386,20 @@ void LoLEngine::setDefaultButtonState() {
_lampStatusSuspended = false;
}
void LoLEngine::generateBlockDrawingBuffer() {
_sceneDrawVarDown = _dscBlockMap[_currentDirection];
_sceneDrawVarRight = _dscBlockMap[_currentDirection + 4];
_sceneDrawVarLeft = _dscBlockMap[_currentDirection + 8];
/*******************************************
* _visibleBlocks map *
* *
* | | | | | | *
* 00 | 01 | 02 | 03 | 04 | 05 | 06 *
* ____|_____|_____|_____|_____|_____|_____ *
* | | | | | | *
* | 07 | 08 | 09 | 10 | 11 | *
* |_____|_____|_____|_____|_____| *
* | | | | *
* | 12 | 13 | 14 | *
* |_____|_____|_____| *
* | | *
* 15 | 16 | 17 *
* | (P) | *
********************************************/
memset(_blockDrawingBuffer, 0, 660 * sizeof(uint16));
_wllProcessFlag = ((_currentBlock >> 5) + (_currentBlock & 0x1f) + _currentDirection) & 1;
if (_wllProcessFlag) // floor and ceiling
generateVmpTileDataFlipped(0, 15, 1, -330, 22, 15);
else
generateVmpTileData(0, 15, 1, -330, 22, 15);
assignVisibleBlocks(_currentBlock, _currentDirection);
uint8 t = _visibleBlocks[0]->walls[_sceneDrawVarRight];
if (t)
generateVmpTileData(-2, 3, t, 102, 3, 5);
t = _visibleBlocks[6]->walls[_sceneDrawVarLeft];
if (t)
generateVmpTileDataFlipped(21, 3, t, 102, 3, 5);
t = _visibleBlocks[1]->walls[_sceneDrawVarRight];
uint8 t2 = _visibleBlocks[2]->walls[_sceneDrawVarDown];
if (hasWall(t) && !(_wllWallFlags[t2] & 8))
generateVmpTileData(2, 3, t, 102, 3, 5);
else if (t && (_wllWallFlags[t2] & 8))
generateVmpTileData(2, 3, t2, 102, 3, 5);
t = _visibleBlocks[5]->walls[_sceneDrawVarLeft];
t2 = _visibleBlocks[4]->walls[_sceneDrawVarDown];
if (hasWall(t) && !(_wllWallFlags[t2] & 8))
generateVmpTileDataFlipped(17, 3, t, 102, 3, 5);
else if (t && (_wllWallFlags[t2] & 8))
generateVmpTileDataFlipped(17, 3, t2, 102, 3, 5);
t = _visibleBlocks[2]->walls[_sceneDrawVarRight];
if (t)
generateVmpTileData(8, 3, t, 97, 1, 5);
t = _visibleBlocks[4]->walls[_sceneDrawVarLeft];
if (t)
generateVmpTileDataFlipped(13, 3, t, 97, 1, 5);
t = _visibleBlocks[1]->walls[_sceneDrawVarDown];
if (hasWall(t))
generateVmpTileData(-4, 3, t, 129, 6, 5);
t = _visibleBlocks[5]->walls[_sceneDrawVarDown];
if (hasWall(t))
generateVmpTileData(20, 3, t, 129, 6, 5);
t = _visibleBlocks[2]->walls[_sceneDrawVarDown];
if (hasWall(t))
generateVmpTileData(2, 3, t, 129, 6, 5);
t = _visibleBlocks[4]->walls[_sceneDrawVarDown];
if (hasWall(t))
generateVmpTileData(14, 3, t, 129, 6, 5);
t = _visibleBlocks[3]->walls[_sceneDrawVarDown];
if (t)
generateVmpTileData(8, 3, t, 129, 6, 5);
t = _visibleBlocks[7]->walls[_sceneDrawVarRight];
if (t)
generateVmpTileData(0, 3, t, 117, 2, 6);
t = _visibleBlocks[11]->walls[_sceneDrawVarLeft];
if (t)
generateVmpTileDataFlipped(20, 3, t, 117, 2, 6);
t = _visibleBlocks[8]->walls[_sceneDrawVarRight];
if (t)
generateVmpTileData(6, 2, t, 81, 2, 8);
t = _visibleBlocks[10]->walls[_sceneDrawVarLeft];
if (t)
generateVmpTileDataFlipped(14, 2, t, 81, 2, 8);
t = _visibleBlocks[8]->walls[_sceneDrawVarDown];
if (hasWall(t))
generateVmpTileData(-4, 2, t, 159, 10, 8);
t = _visibleBlocks[10]->walls[_sceneDrawVarDown];
if (hasWall(t))
generateVmpTileData(16, 2, t, 159, 10, 8);
t = _visibleBlocks[9]->walls[_sceneDrawVarDown];
if (t)
generateVmpTileData(6, 2, t, 159, 10, 8);
t = _visibleBlocks[12]->walls[_sceneDrawVarRight];
if (t)
generateVmpTileData(3, 1, t, 45, 3, 12);
t = _visibleBlocks[14]->walls[_sceneDrawVarLeft];
if (t)
generateVmpTileDataFlipped(16, 1, t, 45, 3, 12);
t = _visibleBlocks[12]->walls[_sceneDrawVarDown];
if (!(_wllWallFlags[t] & 8))
generateVmpTileData(-13, 1, t, 239, 16, 12);
t = _visibleBlocks[14]->walls[_sceneDrawVarDown];
if (!(_wllWallFlags[t] & 8))
generateVmpTileData(19, 1, t, 239, 16, 12);
t = _visibleBlocks[13]->walls[_sceneDrawVarDown];
if (t)
generateVmpTileData(3, 1, t, 239, 16, 12);
t = _visibleBlocks[15]->walls[_sceneDrawVarRight];
t2 = _visibleBlocks[17]->walls[_sceneDrawVarLeft];
if (t)
generateVmpTileData(0, 0, t, 0, 3, 15);
if (t2)
generateVmpTileDataFlipped(19, 0, t2, 0, 3, 15);
}
void LoLEngine::generateVmpTileData(int16 startBlockX, uint8 startBlockY, uint8 vmpMapIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY) {
if (!_wllVmpMap[vmpMapIndex])
return;
uint16 *vmp = &_vmpPtr[(_wllVmpMap[vmpMapIndex] - 1) * 431 + vmpOffset + 330];
for (int i = 0; i < numBlocksY; i++) {
uint16 *bl = &_blockDrawingBuffer[(startBlockY + i) * 22 + startBlockX];
for (int ii = 0; ii < numBlocksX; ii++) {
if ((startBlockX + ii >= 0) && (startBlockX + ii < 22) && *vmp)
*bl = *vmp;
bl++;
vmp++;
}
}
}
void LoLEngine::generateVmpTileDataFlipped(int16 startBlockX, uint8 startBlockY, uint8 vmpMapIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY) {
if (!_wllVmpMap[vmpMapIndex])
return;
uint16 *vmp = &_vmpPtr[(_wllVmpMap[vmpMapIndex] - 1) * 431 + vmpOffset + 330];
for (int i = 0; i < numBlocksY; i++) {
for (int ii = 0; ii < numBlocksX; ii++) {
if ((startBlockX + ii) < 0 || (startBlockX + ii) > 21)
continue;
uint16 v = vmp[i * numBlocksX + (numBlocksX - 1 - ii)];
if (!v)
continue;
if (v & 0x4000)
v -= 0x4000;
else
v |= 0x4000;
_blockDrawingBuffer[(startBlockY + i) * 22 + startBlockX + ii] = v;
}
}
}
bool LoLEngine::hasWall(int index) {
if (!index || (_wllWallFlags[index] & 8))
return false;
return true;
}
void LoLEngine::assignVisibleBlocks(int block, int direction) {
for (int i = 0; i < 18; i++) {
uint16 t = (block + _dscBlockIndex[direction * 18 + i]) & 0x3ff;
_visibleBlockIndex[i] = t;
_visibleBlocks[i] = &_levelBlockProperties[t];
_lvlShapeLeftRight[i] = _lvlShapeLeftRight[18 + i] = -1;
}
}
void LoLEngine::drawVcnBlocks() {
uint8 *d = _sceneWindowBuffer;
uint16 *bdb = _blockDrawingBuffer;
for (int y = 0; y < 15; y++) {
for (int x = 0; x < 22; x++) {
bool horizontalFlip = false;
int remainder = 0;
uint16 vcnOffset = *bdb++;
if (vcnOffset & 0x8000) {
// this renders a wall block over the transparent pixels of a floor/ceiling block
remainder = vcnOffset - 0x8000;
vcnOffset = 0;
}
if (vcnOffset & 0x4000) {
horizontalFlip = true;
vcnOffset &= 0x3fff;
}
uint8 *src = 0;
if (vcnOffset) {
src = &_vcnBlocks[vcnOffset << 5];
} else {
// floor/ceiling blocks
vcnOffset = bdb[329];
if (vcnOffset & 0x4000) {
horizontalFlip = true;
vcnOffset &= 0x3fff;
}
src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset << 5);
}
uint8 shift = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness;
if (horizontalFlip) {
for (int blockY = 0; blockY < 8; blockY++) {
src += 3;
for (int blockX = 0; blockX < 4; blockX++) {
uint8 t = *src--;
*d++ = _vcnExpTable[(t & 0x0f) | shift];
*d++ = _vcnExpTable[(t >> 4) | shift];
}
src += 5;
d += 168;
}
} else {
for (int blockY = 0; blockY < 8; blockY++) {
for (int blockX = 0; blockX < 4; blockX++) {
uint8 t = *src++;
*d++ = _vcnExpTable[(t >> 4) | shift];
*d++ = _vcnExpTable[(t & 0x0f) | shift];
}
d += 168;
}
}
d -= 1400;
if (remainder) {
d -= 8;
horizontalFlip = false;
if (remainder & 0x4000) {
remainder &= 0x3fff;
horizontalFlip = true;
}
shift = _vcnShift ? _vcnShift[remainder] : _blockBrightness;
src = &_vcnBlocks[remainder << 5];
if (horizontalFlip) {
for (int blockY = 0; blockY < 8; blockY++) {
src += 3;
for (int blockX = 0; blockX < 4; blockX++) {
uint8 t = *src--;
uint8 h = _vcnExpTable[(t & 0x0f) | shift];
uint8 l = _vcnExpTable[(t >> 4) | shift];
if (h)
*d = h;
d++;
if (l)
*d = l;
d++;
}
src += 5;
d += 168;
}
} else {
for (int blockY = 0; blockY < 8; blockY++) {
for (int blockX = 0; blockX < 4; blockX++) {
uint8 t = *src++;
uint8 h = _vcnExpTable[(t >> 4) | shift];
uint8 l = _vcnExpTable[(t & 0x0f) | shift];
if (h)
*d = h;
d++;
if (l)
*d = l;
d++;
}
d += 168;
}
}
d -= 1400;
}
}
d += 1232;
}
_screen->copyBlockToPage(_sceneDrawPage1, 112, 0, 176, 120, _sceneWindowBuffer);
}
void LoLEngine::drawSceneShapes() {
for (int i = 0; i < 18; i++) {
uint8 t = _dscTileIndex[i];
uint8 s = _visibleBlocks[t]->walls[_sceneDrawVarDown];
int16 x1 = 0;
int16 x2 = 0;
_shpDmX1 = 0;
_shpDmX2 = 0;
int16 dimY1 = 0;
int16 dimY2 = 0;
setLevelShapesDim(t, x1, x2, 13);
setLevelShapesDim(t, _shpDmX1, _shpDmX2, _sceneShpDim);
if (x2 <= x1)
if (_shpDmX2 <= _shpDmX1)
continue;
drawDecorations(t);
@ -1954,104 +1423,12 @@ void LoLEngine::drawSceneShapes() {
if (v > 80)
v = 80;
scaleLevelShapesDim(t, dimY1, dimY2, 13);
scaleLevelShapesDim(t, dimY1, dimY2, _sceneShpDim);
drawDoor(_doorShapes[(s < 23 ? _dscDoorShpIndex[s] : 0)], 0, t, 10, 0, -v, 2);
setLevelShapesDim(t, dimY1, dimY2, 13);
setLevelShapesDim(t, dimY1, dimY2, _sceneShpDim);
}
}
void LoLEngine::setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim) {
if (_lvlShapeLeftRight[index << 1] == -1) {
x1 = 0;
x2 = 22;
int16 y1 = 0;
int16 y2 = 120;
int m = index * 18;
for (int i = 0; i < 18; i++) {
uint8 d = _visibleBlocks[i]->walls[_sceneDrawVarDown];
uint8 a = _wllWallFlags[d];
if (a & 8) {
int t = _dscDim2[(m + i) << 1];
if (t > x1) {
x1 = t;
if (!(a & 0x10))
scaleLevelShapesDim(index, y1, y2, -1);
}
t = _dscDim2[((m + i) << 1) + 1];
if (t < x2) {
x2 = t;
if (!(a & 0x10))
scaleLevelShapesDim(index, y1, y2, -1);
}
} else {
int t = _dscDim1[m + i];
if (!_wllVmpMap[d] || t == -40)
continue;
if (t == -41) {
x1 = 22;
x2 = 0;
break;
}
if (t > 0 && x2 > t)
x2 = t;
if (t < 0 && x1 < -t)
x1 = -t;
}
if (x2 < x1)
break;
}
x1 += 14;
x2 += 14;
_lvlShapeTop[index] = y1;
_lvlShapeBottom[index] = y2;
_lvlShapeLeftRight[index << 1] = x1;
_lvlShapeLeftRight[(index << 1) + 1] = x2;
} else {
x1 = _lvlShapeLeftRight[index << 1];
x2 = _lvlShapeLeftRight[(index << 1) + 1];
}
drawLevelModifyScreenDim(dim, x1, 0, x2, 15);
}
void LoLEngine::scaleLevelShapesDim(int index, int16 &y1, int16 &y2, int dim) {
static const int8 dscY1[] = { 0x1E, 0x18, 0x10, 0x00 };
static const int8 dscY2[] = { 0x3B, 0x47, 0x56, 0x78 };
uint8 a = _dscDimMap[index];
if (dim == -1 && a != 3)
a++;
y1 = dscY1[a];
y2 = dscY2[a];
if (dim == -1)
return;
const ScreenDim *cDim = _screen->getScreenDim(dim);
_screen->modifyScreenDim(dim, cDim->sx, y1, cDim->w, y2 - y1);
}
void LoLEngine::drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2) {
_screen->modifyScreenDim(dim, x1, y1 << 3, x2 - x1, (y2 - y1) << 3);
}
void LoLEngine::drawDecorations(int index) {
for (int i = 1; i >= 0; i--) {
int s = index * 2 + i;
@ -2066,7 +1443,7 @@ void LoLEngine::drawDecorations(int index) {
if (!scaleW || !scaleH)
continue;
uint8 d = (_currentDirection + _dscUnk1[s]) & 3;
uint8 d = (_currentDirection + _dscWalls[s]) & 3;
int8 l = _wllShapeMap[_visibleBlocks[index]->walls[d]];
uint8 *shapeData = 0;
@ -2076,21 +1453,21 @@ void LoLEngine::drawDecorations(int index) {
int flags = 0;
while (l > 0) {
if ((_levelShapeProperties[l].flags & 8) && index != 3 && index != 9 && index != 13) {
l = _levelShapeProperties[l].next;
if ((_levelDecorationProperties[l].flags & 8) && index != 3 && index != 9 && index != 13) {
l = _levelDecorationProperties[l].next;
continue;
}
if (_dscOvlMap[shpIx] == 1 && ((_levelShapeProperties[l].flags & 2) || ((_levelShapeProperties[l].flags & 4) && _wllProcessFlag)))
if (_dscOvlMap[shpIx] == 1 && ((_levelDecorationProperties[l].flags & 2) || ((_levelDecorationProperties[l].flags & 4) && _wllProcessFlag)))
ix = -ix;
int xOffs = 0;
int yOffs = 0;
uint8 *ovl = 0;
if (_levelShapeProperties[l].scaleFlag[shpIx] & 1) {
xOffs = _levelShapeProperties[l].shapeX[shpIx];
yOffs = _levelShapeProperties[l].shapeY[shpIx];
if (_levelDecorationProperties[l].scaleFlag[shpIx] & 1) {
xOffs = _levelDecorationProperties[l].shapeX[shpIx];
yOffs = _levelDecorationProperties[l].shapeY[shpIx];
shpIx = _dscOvlMap[shpIx];
int ov = ovlIndex;
if (_flags.use16ColorMode) {
@ -2100,8 +1477,8 @@ void LoLEngine::drawDecorations(int index) {
else
ov = 0;
}
ovl = _screen->getLevelOverlay(ov);
} else if (_levelShapeProperties[l].shapeIndex[shpIx] != 0xffff) {
ovl = screen()->getLevelOverlay(ov);
} else if (_levelDecorationProperties[l].shapeIndex[shpIx] != 0xffff) {
scaleW = scaleH = 0x100;
int ov = 7;
if (_flags.use16ColorMode) {
@ -2111,37 +1488,37 @@ void LoLEngine::drawDecorations(int index) {
else
ov = 0;
}
ovl = _screen->getLevelOverlay(ov);
ovl = screen()->getLevelOverlay(ov);
}
if (_levelShapeProperties[l].shapeIndex[shpIx] != 0xffff) {
shapeData = _levelShapes[_levelShapeProperties[l].shapeIndex[shpIx]];
if (_levelDecorationProperties[l].shapeIndex[shpIx] != 0xffff) {
shapeData = _levelDecorationShapes[_levelDecorationProperties[l].shapeIndex[shpIx]];
if (shapeData) {
if (ix < 0) {
x = _dscShapeX[s] + xOffs + ((_levelShapeProperties[l].shapeX[shpIx] * scaleW) >> 8);
x = _dscShapeX[s] + xOffs + ((_levelDecorationProperties[l].shapeX[shpIx] * scaleW) >> 8);
if (ix == _dscShapeIndex[s]) {
x = _dscShapeX[s] - ((_levelShapeProperties[l].shapeX[shpIx] * scaleW) >> 8) -
_screen->getShapeScaledWidth(shapeData, scaleW) - xOffs;
x = _dscShapeX[s] - ((_levelDecorationProperties[l].shapeX[shpIx] * scaleW) >> 8) -
screen()->getShapeScaledWidth(shapeData, scaleW) - xOffs;
}
flags = 0x105;
} else {
x = _dscShapeX[s] + xOffs + ((_levelShapeProperties[l].shapeX[shpIx] * scaleW) >> 8);
x = _dscShapeX[s] + xOffs + ((_levelDecorationProperties[l].shapeX[shpIx] * scaleW) >> 8);
flags = 0x104;
}
y = _dscShapeY[s] + yOffs + ((_levelShapeProperties[l].shapeY[shpIx] * scaleH) >> 8);
_screen->drawShape(_sceneDrawPage1, shapeData, x + 112, y, 13, flags, ovl, 1, scaleW, scaleH);
y = _dscShapeY[s] + yOffs + ((_levelDecorationProperties[l].shapeY[shpIx] * scaleH) >> 8);
screen()->drawShape(_sceneDrawPage1, shapeData, x + 112, y, _sceneShpDim, flags, ovl, 1, scaleW, scaleH);
if ((_levelShapeProperties[l].flags & 1) && shpIx < 4) {
if ((_levelDecorationProperties[l].flags & 1) && shpIx < 4) {
//draw shadow
x += (_screen->getShapeScaledWidth(shapeData, scaleW));
x += (screen()->getShapeScaledWidth(shapeData, scaleW));
flags ^= 1;
_screen->drawShape(_sceneDrawPage1, shapeData, x + 112, y, 13, flags, ovl, 1, scaleW, scaleH);
screen()->drawShape(_sceneDrawPage1, shapeData, x + 112, y, _sceneShpDim, flags, ovl, 1, scaleW, scaleH);
}
}
}
l = _levelShapeProperties[l].next;
l = _levelDecorationProperties[l].next;
shpIx = (_dscShapeIndex[s] < 0) ? -_dscShapeIndex[s] : _dscShapeIndex[s];
}
}

View File

@ -976,6 +976,58 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
}
}
void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage) {
if (srcPage > 13 || dstPage > 13)
error("Screen::crossFadeRegion: attempting to use temp page as source or dest page.");
hideMouse();
uint16 *wB = (uint16*)_pagePtrs[14];
uint8 *hB = _pagePtrs[14] + 640;
for (int i = 0; i < w; i++)
wB[i] = i;
for (int i = 0; i < h; i++)
hB[i] = i;
for (int i = 0; i < w; i++)
SWAP(wB[_vm->_rnd.getRandomNumberRng(0, w - 1)], wB[i]);
for (int i = 0; i < h; i++)
SWAP(hB[_vm->_rnd.getRandomNumberRng(0, h - 1)], hB[i]);
uint8 *s = _pagePtrs[srcPage];
uint8 *d = _pagePtrs[dstPage];
for (int i = 0; i < h; i++) {
int iH = i;
uint32 end = _system->getMillis() + 1;
for (int ii = 0; ii < w; ii++) {
int sX = x1 + wB[ii];
int sY = y1 + hB[iH];
int dX = x2 + wB[ii];
int dY = y2 + hB[iH];
if (++iH >= h)
iH = 0;
d[dY * 320 + dX] = s[sY * 320 + sX];
addDirtyRect(dX, dY, 1, 1);
}
// This tries to speed things up, to get similiar speeds as in DOSBox etc.
if ((i & 5) == 5)
updateScreen();
uint32 cur = _system->getMillis();
if (end > cur)
_system->delayMillis(end - cur);
}
showMouse();
}
void Screen::drawBox(int x1, int y1, int x2, int y2, int color) {
drawClippedLine(x1, y1, x2, y1, color);
drawClippedLine(x1, y1, x1, y2, color);
@ -1088,6 +1140,10 @@ bool Screen::loadFont(FontId fontId, const char *filename) {
if (!fnt) {
if (_isAmiga)
fnt = new AMIGAFont();
#ifdef ENABLE_EOB
else if (_vm->game() == GI_EOB1 || _vm->game() == GI_EOB2)
fnt = new OldDOSFont();
#endif // ENABLE_EOB
else
fnt = new DOSFont();
@ -2859,7 +2915,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette
const char *ext = filename + strlen(filename) - 3;
uint8 compType = srcData[2];
uint32 imgSize = scumm_stricmp(ext, "CMP") ? READ_LE_UINT32(srcData + 4) : READ_LE_UINT16(srcData);
uint32 imgSize = (_vm->game() == GI_KYRA2 && !scumm_stricmp(ext, "CMP")) ? READ_LE_UINT16(srcData) : READ_LE_UINT32(srcData + 4);
uint16 palSize = READ_LE_UINT16(srcData + 8);
if (pal && palSize)

View File

@ -137,6 +137,37 @@ private:
uint16 *_bitmapOffsets;
};
#ifdef ENABLE_EOB
/**
* Implementation of the Font interface for old DOS fonts used
* in EOB and EOB II.
*
*/
class OldDOSFont : public Font {
public:
OldDOSFont();
~OldDOSFont() { unload(); }
bool load(Common::SeekableReadStream &file);
int getHeight() const { return _height; }
int getWidth() const { return _width; }
int getCharWidth(uint16 c) const;
void setColorMap(const uint8 *src) { _colorMap = src; }
void drawChar(uint16 c, byte *dst, int pitch) const;
private:
void unload();
uint8 *_data;
uint16 *_bitmapOffsets;
int _width, _height;
const uint8 *_colorMap;
int _numGlyphs;
};
#endif // ENABLE_EOB
/**
* Implementation of the Font interface for AMIGA fonts.
*/
@ -369,6 +400,8 @@ public:
void shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPage, int ticks, bool transparent);
void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false);
void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
void clearPage(int pageNum);
uint8 getPagePixel(int pageNum, int x, int y);
@ -420,6 +453,8 @@ public:
virtual void setScreenDim(int dim) = 0;
virtual const ScreenDim *getScreenDim(int dim) = 0;
virtual int curDimIndex() const { return 0; }
virtual void modifyScreenDim(int dim, int x, int y, int w, int h) {}
virtual int screenDimTableCount() const = 0;
const ScreenDim *_curDim;
@ -430,13 +465,15 @@ public:
int setNewShapeHeight(uint8 *shape, int height);
int resetShapeHeight(uint8 *shape);
void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
virtual int getShapeScaledWidth( const uint8*, int) { return 0; }
virtual void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
// mouse handling
void hideMouse();
void showMouse();
bool isMouseVisible() const;
void setMouseCursor(int x, int y, const byte *shape);
virtual void setMouseCursor(int x, int y, const byte *shape);
// rect handling
virtual int getRectSize(int w, int h) = 0;
@ -463,6 +500,8 @@ public:
void blockInRegion(int x, int y, int width, int height);
void blockOutRegion(int x, int y, int width, int height);
virtual uint8 *getLevelOverlay(int) { return 0; }
int _charWidth;
int _charOffset;
int _curPage;
@ -514,7 +553,7 @@ protected:
uint8 _sjisInvisibleColor;
Palette *_screenPalette;
Common::Array<Palette *> _palettes;
Common::Array<Palette*> _palettes;
Palette *_internFadePalette;
Font *_fonts[FID_NUM];

965
engines/kyra/screen_eob.cpp Normal file
View File

@ -0,0 +1,965 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#if !defined(ENABLE_EOB)
#include "kyra/screen.h"
#endif
#ifdef ENABLE_EOB
#include "kyra/eobcommon.h"
#include "kyra/resource.h"
#include "common/system.h"
#include "graphics/cursorman.h"
namespace Kyra {
Screen_Eob::Screen_Eob(EobCoreEngine *vm, OSystem *system) : Screen(vm, system) {
_shapeFadeMode[0] = _shapeFadeMode[1] = 0;
_shapeFadeInternal = 0;
_fadeData = 0;
_fadeDataIndex = 0;
_dsX1 = _dsX2 = _dsY1 = _dsY2 = 0;
_customDimTable = 0;
_dsTempPage = 0;
}
Screen_Eob::~Screen_Eob() {
delete[] _fadeData;
delete[] _customDimTable;
delete[] _dsTempPage;
}
bool Screen_Eob::init() {
if (Screen::init()) {
_customDimTable = new ScreenDim*[_screenDimTableCount];
memset(_customDimTable, 0, sizeof(ScreenDim *)* _screenDimTableCount);
_fadeData = _vm->resource()->fileData("FADING.DAT", 0);
if (!_fadeData) {
_fadeData = new uint8[0x700];
memset(_fadeData, 0, 0x700);
uint8 *pal = _vm->resource()->fileData("palette1.pal", 0); // EGA: palette0.pal
for (int i = 0; i < 7; i++)
createFadeTable(pal, &_fadeData[i << 8], 18, (i + 1) * 36);
delete[] pal;
}
_dsTempPage = new uint8[6000];
return true;
}
return false;
}
void Screen_Eob::setScreenDim(int dim) {
assert(dim < _screenDimTableCount);
_curDim = _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
_curDimIndex = dim;
}
const ScreenDim *Screen_Eob::getScreenDim(int dim) {
assert(dim < _screenDimTableCount);
return _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
}
void Screen_Eob::modifyScreenDim(int dim, int x, int y, int w, int h) {
delete _customDimTable[dim];
_customDimTable[dim] = new ScreenDim;
memcpy(_customDimTable[dim], &_screenDimTable[dim], sizeof(ScreenDim));
_customDimTable[dim]->sx = x;
_customDimTable[dim]->sy = y;
_customDimTable[dim]->w = w;
_customDimTable[dim]->h = h;
if (dim == _curDimIndex)
setScreenDim(dim);
}
void Screen_Eob::setClearScreenDim(int dim) {
setScreenDim(dim);
clearCurDim();
}
void Screen_Eob::clearCurDim() {
fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA);
}
void Screen_Eob::setMouseCursor(int x, int y, const byte *shape) {
if (!shape)
return;
int mouseW = shape[2] << 3;
int mouseH = shape[3];
uint8 *cursor = new uint8[mouseW * mouseH];
fillRect(0, 0, mouseW, mouseH, _cursorColorKey, 8);
drawShape(8, shape, 0, 0, 0);
CursorMan.showMouse(false);
copyRegionToBuffer(8, 0, 0, mouseW, mouseH, cursor);
CursorMan.replaceCursor(cursor, mouseW, mouseH, x, y, _cursorColorKey);
if (isMouseVisible())
CursorMan.showMouse(true);
delete[] cursor;
// makes sure that the cursor is drawn
// we do not use Screen::updateScreen here
// so we can be sure that changes to page 0
// are NOT updated on the real screen here
_system->updateScreen();
}
void Screen_Eob::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size) {
s->read(_pagePtrs[pageNum], size);
}
void Screen_Eob::printShadedText(const char *string, int x, int y, int col1, int col2) {
printText(string, x - 1, y, 12, col2);
printText(string, x, y + 1, 12, 0);
printText(string, x - 1, y + 1, 12, 0);
printText(string, x, y, col1, 0);
}
void Screen_Eob::loadEobBitmap(const char *file, int tempPage, int destPage) {
loadEobCpsFileToPage(file, 0, tempPage, destPage, -1);
_curPage = 2;
}
void Screen_Eob::loadEobCpsFileToPage(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage) {
char tmp[13];
sprintf(tmp, "%s.CPS", file);
Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp);
bool loadAlternative = false;
if (s) {
// This additional check is necessary since some localized versions of EOB II seem to contain invalid (size zero) cps files
if (s->size())
loadBitmap(tmp, tempPage, destPage, 0);
else
loadAlternative = true;
delete s;
} else {
loadAlternative = true;
}
if (loadAlternative) {
tmp[0] = 'X';
s = _vm->resource()->createReadStream(tmp);
if (!s)
error("Screen_Eob::loadEobCpsFileToPage(): CPS file loading failed.");
s->seek(768);
loadFileDataToPage(s, destPage, 64000);
delete s;
}
if (copyToPage == -1) {
return;
} else if (copyToPage == 0) {
copyPage(destPage, 2);
copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
} else {
copyPage(destPage, copyToPage);
}
}
uint8 *Screen_Eob::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool flag) {
uint8 *shp = 0;
uint16 shapesize = 0;
uint8 *srcPage = getPagePtr(_curPage) + y * 320 + (x << 3);
uint8 *src = srcPage;
if (flag) {
uint16 h1 = h;
while (h1--) {
uint8 *lineEnd = src + (w << 3);
do {
if (!*src++) {
shapesize++;
uint8 *startZeroPos = src;
while (src != lineEnd && *src == 0)
src++;
uint16 numZero = src - startZeroPos + 1;
if (numZero >> 8)
shapesize += 2;
}
shapesize++;
} while (src != lineEnd);
srcPage += 320;
src = srcPage;
}
shapesize += 4;
shp = new uint8[shapesize];
memset (shp, 0, shapesize);
uint8 *dst = shp;
*dst++ = 0;
*dst++ = (h & 0xff);
*dst++ = (w & 0xff);
*dst++ = (h & 0xff);
srcPage = getPagePtr(_curPage) + y * 320 + (x << 3);
src = srcPage;
h1 = h;
while (h1--) {
uint8 *lineEnd = src + (w << 3);
do {
uint8 val = *src++;
if (!val) {
*dst++ = val;
uint8 *startZeroPos = src;
while (src != lineEnd && *src == 0)
src++;
uint16 numZero = src - startZeroPos + 1;
if (numZero >> 8) {
numZero -= 0xff;
*dst++ = 0xff;
*dst++ = 0;
}
val = (numZero & 0xff);
}
*dst++ = val;
} while (src != lineEnd);
srcPage += 320;
src = srcPage;
}
} else {
uint8 nib = 0, col = 0;
uint8 *colorMap = new uint8[0x100];
memset (colorMap, 0xff, 0x100);
shapesize = h * (w << 2) + 0x14;
shp = new uint8[shapesize];
memset (shp, 0, shapesize);
uint8 *dst = shp;
*dst++ = 1;
*dst++ = (h & 0xff);
*dst++ = (w & 0xff);
*dst++ = (h & 0xff);
memset (dst, 0xff, 0x10);
uint8 *pal = dst;
dst += 0x10;
srcPage = getPagePtr(_curPage) + y * 320 + (x << 3);
src = srcPage;
nib = col = 0;
uint16 h1 = h;
while (h1--) {
uint16 w1 = w << 3;
while (w1--) {
uint8 s = *src++;
uint8 c = colorMap[s];
if (c == 0xff) {
if (col < 0x10) {
*pal++ = s;
c = colorMap[s] = col++;
if (!col)
c = 0;
} else {
c = 0;
}
}
if(++nib & 1) {
*dst = c << 4;
} else {
*dst++ |= c;
}
}
srcPage += 320;
src = srcPage;
}
delete [] colorMap;
}
return shp;
}
void Screen_Eob::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) {
uint8 *dst = getPagePtr(pageNum);
const uint8 *src = shapeData;
if (!src)
return;
va_list args;
va_start(args, flags);
uint8 *ovl = (flags & 2) ? va_arg(args, uint8*) : 0;
va_end(args);
if (sd != -1) {
const ScreenDim *dm = getScreenDim(sd);
setShapeFrame(dm->sx, dm->sy, dm->sx + dm->w, dm->sy + dm->h);
x += (_dsX1 << 3);
y += _dsY1;
}
dst += (_dsX1 << 3);
int16 dX = x - (_dsX1 << 3);
int16 dY = y;
int16 dW = _dsX2 - _dsX1;
uint8 flag = *src++;
uint16 dH = *src++;
uint16 width = (*src++) << 3;
src++;
int rX = x;
int rY = y;
int rW = width + 8;
int rH = dH;
uint16 w2 = width;
int d = dY - _dsY1;
int pixelStep = (flags & 1) ? -1 : 1;
if (flag) {
const uint8 *pal = ovl ? ovl : src;
src += 16;
if (d < 0) {
d = -d;
if (d >= dH)
return;
src += (d * (width >> 1));
d = dY + dH - _dsY1;
if (d >=0) {
dH = d;
dY = _dsY1;
d = _dsY2 - dY;
}
} else {
d = _dsY2 - dY;
}
if (d < 1)
return;
if (d < dH)
dH = d;
int16 cnt1 = 0;
int16 cnt2 = 0;
int16 dXbit1 = dX & 1;
if (dX < 0) {
width += dX;
d = -dX;
if ((flags & 1))
src -= (d >> 1);
else
src += (d >> 1);
if (d >= w2)
return;
dX = 0;
cnt1++;
}
d = (dW << 3) - dX;
if (d < 1)
return;
if (d < width) {
width = d;
cnt2++;
}
dst += (dY * 320 + dX);
if (pageNum == 0 || pageNum == 1)
addDirtyRect(rX, rY, rW, rH);
int w3 = w2;
dY = 320 - width;
width >>= 1;
w2 >>= 1;
if ((flags & 1))
src += (w2 - 1);
int16 w1shr = width;
if (cnt1 && (dXbit1 & 1)) {
w1shr++;
w2++;
if (!cnt2)
dY += 2;
}
if (cnt2 && (dXbit1 & 1))
w1shr++;
int lineSrcStep = (w2 - w1shr);
if ((flags & 1))
lineSrcStep = w3 - lineSrcStep;
while (dH--) {
int16 hpos = width;
uint8 col = 0;
uint8 b = 0;
uint8 nextloop = 0;
if (cnt1 && dXbit1) {
if (!hpos)
return;
b = *src;
src += pixelStep;
nextloop = 2;
} else {
nextloop = hpos ? 1 : 3;
}
while (nextloop) {
switch (nextloop) {
case 1:
b = *src;
src += pixelStep;
col = pal[(flags & 1) ? (b & 0x0f) : (b >> 4)];
if (col)
drawShapeSetPixel(dst, col);
dst++;
case 2:
col = pal[(flags & 1) ? (b >> 4) : (b & 0x0f)];
if (!col) {
nextloop = 4;
break;
}
drawShapeSetPixel(dst++, col);
nextloop = --hpos ? 1 : 3;
break;
case 3:
if (cnt2 && dXbit1) {
col = pal[(flags & 1) ? (*src & 0x0f) : (*src >> 4)];
src += pixelStep;
if (col)
drawShapeSetPixel(dst, col);
dst++;
}
src += lineSrcStep;
dst += dY;
nextloop = 0;
break;
case 4:
dst++;
nextloop = --hpos ? 1 : 3;
break;
}
}
}
} else {
uint16 marginLeft = 0;
uint16 marginRight = 0;
if (d < 0) {
dH += d;
if (dH <= 0)
return;
d = -d;
for (int ii = 0; ii < d; ii++) {
marginLeft = width;
int i = 0;
do {
for (i = 0; i < marginLeft; i++)
if (!*src++)
break;
if (!*(src-1) || i < marginLeft)
marginLeft = ++marginLeft - *src++;
else
marginLeft = 0;
} while (marginLeft);
}
dY = _dsY1;
}
d = _dsY2 - dY;
if (d < 1)
return;
if (d < dH)
dH = d;
marginLeft = 0;
if (dX < 0) {
width += dX;
marginLeft = -dX;
if (marginLeft >= w2)
return;
dX = 0;
}
marginRight = 0;
d = (dW << 3) - dX;
if (d < 1)
return;
if (d < width) {
width = d;
marginRight = w2 - marginLeft - width;
}
dst += (y * 320 + dX);
uint8 * dstL = dst;
if (pageNum == 0 || pageNum == 1)
addDirtyRect(rX, rY, rW, rH);
while (dH--) {
int16 xpos = (int16) marginLeft;
if (xpos) {
do {
while (*src && xpos) {
src++;
xpos--;
}
if (!*src) {
uint8 bt = *++src;
src++;
xpos = xpos - bt;
}
} while (xpos > 0);
}
dst -= xpos;
xpos += width;
while (xpos > 0) {
uint8 c = *src++;
if (c) {
drawShapeSetPixel(dst++, c);
xpos--;
} else {
dst += *src;
xpos -= *src++;
}
}
xpos += marginRight;
if (xpos) {
do {
while (*src && xpos) {
src++;
xpos--;
}
if (!*src) {
uint8 bt = *++src;
src++;
xpos = xpos - bt;
}
} while (xpos > 0);
}
dstL += 320;
dst = dstL;
}
}
}
void Screen_Eob::drawShapeSetPixel(uint8 * dst, uint8 c) {
if (_shapeFadeMode[0]) {
if (_shapeFadeMode[1]) {
c = *dst;
} else {
_shapeFadeInternal &= 7;
c = *(dst + _shapeFadeInternal++);
}
}
if (_shapeFadeMode[1]) {
uint8 cnt = _shapeFadeMode[1];
while (cnt--)
c = _fadeData[_fadeDataIndex + c];
}
*dst = c;
}
const uint8 *Screen_Eob::scaleShape(const uint8 *shapeData, int steps) {
setShapeFadeMode(1, steps ? true : false);
while (shapeData && steps--)
shapeData = scaleShapeStep(shapeData);
return shapeData;
}
const uint8 *Screen_Eob::scaleShapeStep(const uint8 *shp) {
uint8 *d = _dsTempPage;
*d++ = *shp++;
uint16 h = (*shp++) + 1;
d[0] = d[2] = (h << 1) / 3;
d++;
uint16 w = *shp++;
uint16 w2 = w << 2;
uint16 t = ((w << 1) % 3) ? 1 : 0;
*d++ = ((w << 1) / 3) + t;
shp++;
d++;
int i = 0;
while (i < 16) {
if (!shp[i]) {
i = -i;
break;
}
i++;
}
if (i >= 0)
i = 0;
else
i = -i;
_dsScaleTmp = (i << 4) | (i & 0x0f);
memcpy(d, shp, 16);
d += 16;
shp += 16;
_dsDiv = w2 / 3;
_dsRem = w2 % 3;
do {
scaleShapeProcessLine(d, shp);
if (!--h)
break;
scaleShapeProcessLine(d, shp);
if (!--h)
break;
shp += w2;
} while (--h);
return (const uint8 *) _dsTempPage;
}
void Screen_Eob::replaceShapePalette(uint8 *shp, const uint8 *pal) {
if (*shp != 1)
return;
shp += 4;
memcpy(shp, pal, 16);
}
void Screen_Eob::applyShapeOverlay(uint8 *shp, int ovlIndex) {
if (*shp != 1)
return;
shp += 4;
uint8 *ovl = getFadeTable(ovlIndex);
for (int i = 0; i < 16; i++)
shp[i] = ovl[shp[i]];
}
void Screen_Eob::scaleShapeProcessLine(uint8 *&dst, const uint8 *&src) {
for (int i = 0; i < _dsDiv; i++) {
*dst++ = *src++;
*dst++ = READ_BE_UINT16(src) >> 4;
src += 2;
}
if (_dsRem == 1) {
*dst++ = *src++;
*dst++ = _dsScaleTmp;
} if (_dsRem == 2) {
*dst++ = (src[0] & 0xf0) | (src[1] >> 4);
src += 2;
*dst++ = _dsScaleTmp;
*dst++ = _dsScaleTmp;
*dst++ = _dsScaleTmp;
}
}
void Screen_Eob::fadeTextColor(Palette *pal, int color1, int rate) {
uint8 *col = pal->getData();
for (bool loop = true; loop; ) {
loop = true;
uint32 end = _system->getMillis() + 16;
loop = false;
for (int ii = 0; ii < 3; ii++) {
uint8 c = col[color1 * 3 + ii];
if (c > rate) {
col[color1 * 3 + ii] -= rate;
loop = true;
} else if (c) {
col[color1 * 3 + ii] = 0;
loop = true;
}
}
if (loop) {
setScreenPalette(*pal);
updateScreen();
uint32 cur = _system->getMillis();
if (end > cur)
_system->delayMillis(end - cur);
}
}
}
bool Screen_Eob::delayedFadePalStep(Palette *fadePal, Palette *destPal, int rate) {
bool res = false;
uint8 *s = fadePal->getData();
uint8 *d = destPal->getData();
for (int i = 0; i < 765; i++) {
int fadeVal = *s++;
int dstCur = *d;
int diff = ABS(fadeVal - dstCur);
if (diff == 0) {
d++;
continue;
}
res = true;
diff = MIN(diff, rate);
if (dstCur < fadeVal)
*d += diff;
else
*d -= diff;
d++;
}
return res;
}
void Screen_Eob::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
if (!palData)
return;
uint8 *src = palData + 3 * rootColor;
uint8 r = *src++;
uint8 g = *src++;
uint8 b = *src;
uint8 tr, tg, tb;
src = palData + 3;
*dst++ = 0;
weight >>= 1;
for (uint8 i = 1; i; i++) {
uint16 tmp = (uint16)((*src - r) * weight) << 1;
tr = *src++ - ((tmp >> 8) & 0xff);
tmp = (uint16)((*src - g) * weight) << 1;
tg = *src++ - ((tmp >> 8) & 0xff);
tmp = (uint16)((*src - b) * weight) << 1;
tb = *src++ - ((tmp >> 8) & 0xff);
uint8 * d = palData + 3;
uint16 v = 0xffff;
uint8 col = rootColor;
for (uint8 ii = 1; ii; ii++) {
int a = *d++ - tr;
int t = a * a;
a = *d++ - tg;
t += (a * a);
a = *d++ - tb;
t += (a * a);
if (t <= v && (ii == rootColor || ii != i)) {
v = t;
col = ii ;
}
}
*dst++ = col;
}
}
OldDOSFont::OldDOSFont() {
_data = 0;
_width = _height = _numGlyphs = 0;
_bitmapOffsets = 0;
}
bool OldDOSFont::load(Common::SeekableReadStream &file) {
unload();
_data = new uint8[file.size()];
assert(_data);
file.read(_data, file.size());
if (file.err())
return false;
if (file.size() - 2 != READ_LE_UINT16(_data))
return false;
_width = _data[0x103];
_height = _data[0x102];
_numGlyphs = 255;
_bitmapOffsets = (uint16 *)(_data + 2);
for (int i = 0; i < _numGlyphs; ++i)
_bitmapOffsets[i] = READ_LE_UINT16(&_bitmapOffsets[i]);
return true;
}
int OldDOSFont::getCharWidth(uint16 c) const {
if (c >= _numGlyphs)
return 0;
return _width;
}
void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {
static const uint8 renderMaskTable6[] = { 0xFC, 0x00, 0x7E, 0x00, 0x3F, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8 };
static const uint8 renderMaskTable8[] = { 0xFF, 0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE };
if (_width != 8 && _width != 6)
error("EOB font rendering not implemented for other font widths than 6 and 8.");
if (_width == 6) {
switch (c) {
case 0x81:
case 0x9a:
c = 0x5d;
break;
case 0x84:
case 0x8e:
c = 0x5b;
break;
case 0x94:
case 0x99:
c = 0x40;
case 0xe1:
// TODO: recheck this: no conversion for 'ß' ?
break;
}
} else if (_width == 8){
switch (c) {
case 0x81:
case 0x9a:
case 0x5d:
c = 0x1d;
break;
case 0x84:
case 0x5b:
c = 0x1e;
break;
case 0x94:
case 0x40:
c = 0x1f;
break;
case 0x8e:
c = 0x1b;
break;
case 0x99:
c = 0x1c;
break;
case 0xe1:
c = 0x19;
break;
}
}
const uint8 *src = &_data[_bitmapOffsets[c]];
int w = (_width - 1) >> 3;
pitch -= _width;
uint8 color1 = _colorMap[1];
uint8 color2 = _colorMap[0];
int cH = _height;
while (cH--) {
int cW = w;
const uint8 *mtbl = _width == 8 ? renderMaskTable8 : renderMaskTable6;
for (bool runWidthLoop = true; runWidthLoop; ) {
uint8 s = *src++;
uint8 m = *mtbl++;
for (uint8 i = 0x80; i; i >>= 1) {
if (!(m & i)) {
runWidthLoop = false;
break;
}
if (s & i) {
if (color1)
*dst = color1;
} else if (color2) {
*dst = color2;
}
dst++;
}
if (cW)
cW--;
else
runWidthLoop = false;
}
dst += pitch;
}
}
void OldDOSFont::unload() {
delete[] _data;
_data = 0;
_width = _height = _numGlyphs = 0;
_bitmapOffsets = 0;
}
} // End of namespace Kyra
#endif // ENABLE_EOB

105
engines/kyra/screen_eob.h Normal file
View File

@ -0,0 +1,105 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef KYRA_SCREEN_EOB_H
#define KYRA_SCREEN_EOB_H
#ifdef ENABLE_EOB
#include "kyra/screen.h"
namespace Kyra {
class EobCoreEngine;
class Screen_Eob : public Screen{
public:
Screen_Eob(EobCoreEngine *vm, OSystem *system);
virtual ~Screen_Eob();
bool init();
void setScreenDim(int dim);
const ScreenDim *getScreenDim(int dim);
int curDimIndex() const { return _curDimIndex; }
void modifyScreenDim(int dim, int x, int y, int w, int h);
int screenDimTableCount() const { return _screenDimTableCount; }
void setClearScreenDim(int dim);
void clearCurDim();
void setMouseCursor(int x, int y, const byte *shape);
void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size);
void printShadedText(const char *string, int x, int y, int col1, int col2);
void loadEobCpsFileToPage(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage);
void loadEobBitmap(const char *file, int tempPage, int destPage);
uint8 *encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool flag = false);
void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd = -1, int flags = 0, ...);
const uint8 *scaleShape(const uint8 *shapeData, int blockDistance);
const uint8 *scaleShapeStep(const uint8 *shp);
void replaceShapePalette(uint8 *shp, const uint8 *pal);
void applyShapeOverlay(uint8 *shp, int ovlIndex);
void setShapeFrame(int x1, int y1, int x2, int y2) { _dsX1 = x1; _dsY1 = y1; _dsX2 = x2; _dsY2 = y2; }
void setShapeFadeMode (uint8 i, bool b) { if (!i || i == 1) _shapeFadeMode[i] = b; }
void fadeTextColor(Palette *pal, int color1, int fadeTextColor);
bool delayedFadePalStep(Palette *fadePal, Palette *destPal, int rate);
void setTextColorMap(const uint8 *cmap) {}
int getRectSize(int w, int h) { return w * h; }
void setFadeTableIndex(int index) { _fadeDataIndex = (CLIP(index, 0, 7) << 8); }
void createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);
uint8 *getFadeTable(int index) { return (index >= 0 && index < 5) ? &_fadeData[index << 8] : 0; }
protected:
int16 _dsX1, _dsX2, _dsY1, _dsY2;
bool _shapeFadeMode[2];
uint16 _shapeFadeInternal;
uint8 *_fadeData;
int _fadeDataIndex;
uint8 *_dsTempPage;
static const ScreenDim _screenDimTable[];
static const int _screenDimTableCount;
ScreenDim **_customDimTable;
int _curDimIndex;
private:
void drawShapeSetPixel(uint8 *dst, uint8 c);
void scaleShapeProcessLine(uint8 *&dst, const uint8 *&src);
int _dsDiv, _dsRem, _dsScaleTmp;
};
} // End of namespace Kyra
#endif // ENABLE_EOB
#endif

View File

@ -95,7 +95,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
return false;
}
bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode *> *opcodes) {
bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode*> *opcodes) {
Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
if (!stream) {
error("Couldn't open script file '%s'", filename);

View File

@ -41,7 +41,7 @@ struct EMCData {
uint16 *ordr;
uint16 dataSize;
const Common::Array<const Opcode *> *sysFuncs;
const Common::Array<const Opcode*> *sysFuncs;
};
struct EMCState {
@ -92,7 +92,7 @@ class EMCInterpreter {
public:
EMCInterpreter(KyraEngine_v1 *vm);
bool load(const char *filename, EMCData *data, const Common::Array<const Opcode *> *opcodes);
bool load(const char *filename, EMCData *data, const Common::Array<const Opcode*> *opcodes);
void unload(EMCData *data);
void init(EMCState *scriptState, const EMCData *data);

1528
engines/kyra/script_eob.cpp Normal file

File diff suppressed because it is too large Load Diff

121
engines/kyra/script_eob.h Normal file
View File

@ -0,0 +1,121 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#ifdef ENABLE_EOB
#ifndef KYRA_SCRIPT_EOB_H
#define KYRA_SCRIPT_EOB_H
#include "common/func.h"
#include "common/substream.h"
#include "common/savefile.h"
namespace Kyra {
class LolEobBaseEngine;
class EobInfProcessor {
public:
EobInfProcessor(EobCoreEngine *engine, Screen_Eob *_screen);
~EobInfProcessor();
void loadData(const uint8 *data, uint32 dataSize);
void run(int func, int sub);
void setFlag(int flag) { _flagTable[17] |= flag; }
bool checkFlag(int flag) { return (_flagTable[17] & flag) ? true : false; }
void loadState(Common::SeekableSubReadStreamEndian &in);
void saveState(Common::OutSaveFile *out);
private:
const char *getString(uint16 index);
int oeob_setWallType(int8 *data);
int oeob_toggleWallState(int8 *data);
int oeob_openDoor(int8 *data);
int oeob_closeDoor(int8 *data);
int oeob_replaceMonster(int8 *data);
int oeob_movePartyOrObject(int8 *data);
int oeob_moveInventoryItemToBlock(int8 *data);
int oeob_printMessage_v1(int8 *data);
int oeob_printMessage_v2(int8 *data);
int oeob_setFlags(int8 *data);
int oeob_playSoundEffect(int8 *data);
int oeob_removeFlags(int8 *data);
int oeob_modifyCharacterHitPoints(int8 *data);
int oeob_calcAndInflictCharacterDamage(int8 *data);
int oeob_jump(int8 *data);
int oeob_end(int8 *data);
int oeob_popPosAndReturn(int8 *data);
int oeob_pushPosAndJump(int8 *data);
int oeob_eval_v1(int8 *data);
int oeob_eval_v2(int8 *data);
int oeob_deleteItem(int8 *data);
int oeob_loadNewLevelOrMonsters(int8 *data);
int oeob_increasePartyExperience(int8 *data);
int oeob_createItem_v1(int8 *data);
int oeob_createItem_v2(int8 *data);
int oeob_launchObject(int8 *data);
int oeob_changeDirection(int8 *data);
int oeob_identifyItems(int8 *data);
int oeob_sequence(int8 *data);
int oeob_delay(int8 *data);
int oeob_drawScene(int8 *data);
int oeob_dialogue(int8 *data);
int oeob_specialEvent(int8 *data);
EobCoreEngine *_vm;
Screen_Eob *_screen;
typedef Common::Functor1Mem<int8*, int, EobInfProcessor> InfProc;
Common::Array<const InfProc*> _opcodes;
int8 *_scriptData;
uint8 _abortScript;
uint16 _abortAfterSubroutine;
int _dlgResult;
uint8 _script2;
uint16 _lastScriptFunc;
uint16 _lastScriptSub;
int8 **_scriptPosStack;
int _scriptPosStackIndex;
uint32 *_flagTable;
int16 *_stack;
int _stackIndex;
int8 _activeCharacter;
const int _commandMin;
};
} // End of namespace Kyra
#endif
#endif // ENABLE_EOB

View File

@ -1480,7 +1480,7 @@ typedef Common::Functor2Mem<const TIM *, const uint16 *, int, KyraEngine_HoF> TI
#define OpcodeTimUnImpl() _timOpcodes.push_back(new TIMOpcodeV2(this, 0))
void KyraEngine_HoF::setupOpcodeTable() {
Common::Array<const Opcode *> *table = 0;
Common::Array<const Opcode*> *table = 0;
_opcodes.reserve(176);
SetOpcodeTable(_opcodes);

View File

@ -1754,7 +1754,7 @@ typedef Common::Functor1Mem<EMCState *, int, KyraEngine_LoK> OpcodeV1;
#define SetOpcodeTable(x) table = &x;
#define Opcode(x) table->push_back(new OpcodeV1(this, &KyraEngine_LoK::x))
void KyraEngine_LoK::setupOpcodeTable() {
Common::Array<const Opcode *> *table = 0;
Common::Array<const Opcode*> *table = 0;
_opcodes.reserve(157);
SetOpcodeTable(_opcodes);

View File

@ -93,25 +93,6 @@ void LoLEngine::runLevelScriptCustom(int block, int flags, int charNum, int item
checkSceneUpdateNeed(block);
}
bool LoLEngine::checkSceneUpdateNeed(int func) {
if (_sceneUpdateRequired)
return true;
for (int i = 0; i < 15; i++) {
if (_visibleBlockIndex[i] == func) {
_sceneUpdateRequired = true;
return true;
}
}
if (_currentBlock == func){
_sceneUpdateRequired = true;
return true;
}
return false;
}
int LoLEngine::olol_setWallType(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setWallType(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
if (stackPos(2) != -1) {
@ -796,9 +777,9 @@ int LoLEngine::olol_updateBlockAnimations(EMCState *script) {
return 0;
}
int LoLEngine::olol_mapShapeToBlock(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_mapShapeToBlock(%p) (%d)", (const void *)script, stackPos(0));
return assignLevelShapes(stackPos(0));
int LoLEngine::olol_assignLevelDecorationShape(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_assignLevelDecorationShape(%p) (%d)", (const void *)script, stackPos(0));
return assignLevelDecorationShapes(stackPos(0));
}
int LoLEngine::olol_resetBlockShapeAssignment(EMCState *script) {
@ -830,11 +811,11 @@ int LoLEngine::olol_initMonster(EMCState *script) {
return -1;
for (uint8 i = 0; i < 30; i++) {
MonsterInPlay *l = &_monsters[i];
LolMonsterInPlay *l = &_monsters[i];
if (l->hitPoints || l->mode == 13)
continue;
memset(l, 0, sizeof(MonsterInPlay));
memset(l, 0, sizeof(LolMonsterInPlay));
l->id = i;
l->x = x;
l->y = y;
@ -945,7 +926,7 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
stackPos(28), stackPos(29), stackPos(30), stackPos(31), stackPos(32), stackPos(33), stackPos(34),
stackPos(35), stackPos(36), stackPos(37), stackPos(38), stackPos(39), stackPos(40), stackPos(41));
MonsterProperty *l = &_monsterProperties[stackPos(0)];
LolMonsterProperty *l = &_monsterProperties[stackPos(0)];
l->shapeIndex = stackPos(1) & 0xff;
int shpWidthMax = 0;
@ -1017,7 +998,7 @@ int LoLEngine::olol_inflictDamage(EMCState *script) {
int LoLEngine::olol_moveMonster(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveMonster(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
MonsterInPlay *m = &_monsters[stackPos(0)];
LolMonsterInPlay *m = &_monsters[stackPos(0)];
if (m->mode == 1 || m->mode == 2) {
calcCoordinates(m->destX, m->destY, stackPos(1), stackPos(2), stackPos(3));
@ -1029,10 +1010,9 @@ int LoLEngine::olol_moveMonster(EMCState *script) {
return 1;
}
int LoLEngine::olol_dialogueBox(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_dialogueBox(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_tim->drawDialogueBox(stackPos(0), getLangString(stackPos(1)), getLangString(stackPos(2)), getLangString(stackPos(3)));
int LoLEngine::olol_setupDialogueButtons(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setupDialogueButtons(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
setupDialogueButtons(stackPos(0), getLangString(stackPos(1)), getLangString(stackPos(2)), getLangString(stackPos(3)));
return 1;
}
@ -1194,7 +1174,7 @@ int LoLEngine::olol_playSoundEffect(EMCState *script) {
int LoLEngine::olol_processDialogue(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_processDialogue(%p)", (const void *)script);
return _tim->processDialogue();
return processDialogue();
}
int LoLEngine::olol_stopTimScript(EMCState *script) {
@ -1213,7 +1193,7 @@ int LoLEngine::olol_changeMonsterStat(EMCState *script) {
if (stackPos(0) == -1)
return 1;
MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
LolMonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
int16 d = stackPos(2);
uint16 x = 0;
@ -1254,7 +1234,7 @@ int LoLEngine::olol_getMonsterStat(EMCState *script) {
if (stackPos(0) == -1)
return 0;
MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
LolMonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
int d = stackPos(1);
switch (d) {
@ -1567,7 +1547,7 @@ int LoLEngine::olol_moveBlockObjects(EMCState *script) {
l &= 0x7fff;
MonsterInPlay *m = &_monsters[l];
LolMonsterInPlay *m = &_monsters[l];
setMonsterMode(m, 14);
checkSceneUpdateNeed(m->block);
@ -1582,8 +1562,8 @@ int LoLEngine::olol_moveBlockObjects(EMCState *script) {
placeMoveLevelItem(l, level, destBlock, _itemsInPlay[l].x & 0xff, _itemsInPlay[l].y & 0xff, _itemsInPlay[l].flyingHeight);
res = 1;
if (!runScript || level != _currentLevel)
continue;
if (!runScript || level != _currentLevel)
continue;
runLevelScriptCustom(destBlock, 0x80, -1, l, 0, 0);
}
@ -1638,7 +1618,7 @@ int LoLEngine::olol_dummy1(EMCState *script) {
int LoLEngine::olol_suspendMonster(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_suspendMonster(%p) (%d)", (const void *)script, stackPos(0));
MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
LolMonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
setMonsterMode(m, 14);
checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
@ -1889,9 +1869,9 @@ int LoLEngine::olol_checkBlockForMonster(EMCState *script) {
return -1;
}
int LoLEngine::olol_transformRegion(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_transformRegion(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
transformRegion(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
int LoLEngine::olol_crossFadeRegion(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_crossFadeRegion(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
_screen->crossFadeRegion(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
return 1;
}
@ -1984,7 +1964,7 @@ int LoLEngine::olol_getAnimationLastPart(EMCState *script) {
int LoLEngine::olol_assignSpecialGuiShape(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_assignSpecialGuiShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
if (stackPos(0)) {
_specialGuiShape = _levelShapes[_levelShapeProperties[_wllShapeMap[stackPos(0)]].shapeIndex[stackPos(1)]];
_specialGuiShape = _levelDecorationShapes[_levelDecorationProperties[_wllShapeMap[stackPos(0)]].shapeIndex[stackPos(1)]];
_specialGuiShapeX = stackPos(2);
_specialGuiShapeY = stackPos(3);
_specialGuiShapeMirrorFlag = stackPos(4);
@ -2291,10 +2271,10 @@ int LoLEngine::olol_calcNewBlockPosition(EMCState *script) {
return calcNewBlockPosition(stackPos(0), stackPos(1));
}
int LoLEngine::olol_fadeScene(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_fadeScene(%p)", (const void *)script);
int LoLEngine::olol_crossFadeScene(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_crossFadeScene(%p)", (const void *)script);
gui_drawScene(2);
transformRegion(112, 0, 112, 0, 176, 120, 2, 0);
_screen->crossFadeRegion(112, 0, 112, 0, 176, 120, 2, 0);
updateDrawPage2();
return 1;
}
@ -2700,7 +2680,7 @@ typedef Common::Functor2Mem<const TIM *, const uint16 *, int, LoLEngine> TIMOpco
#define OpcodeTimUnImpl() timTable->push_back(new TIMOpcodeLoL(this, 0))
void LoLEngine::setupOpcodeTable() {
Common::Array<const Opcode *> *table = 0;
Common::Array<const Opcode*> *table = 0;
_opcodes.reserve(192);
SetOpcodeTable(_opcodes);
@ -2784,7 +2764,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x34
Opcode(olol_updateBlockAnimations);
Opcode(olol_mapShapeToBlock);
Opcode(olol_assignLevelDecorationShape);
Opcode(olol_resetBlockShapeAssignment);
Opcode(olol_copyRegion);
@ -2808,7 +2788,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x44
Opcode(olol_moveMonster);
Opcode(olol_dialogueBox);
Opcode(olol_setupDialogueButtons);
Opcode(olol_giveTakeMoney);
Opcode(olol_checkMoney);
@ -2933,7 +2913,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_checkBlockForMonster);
// 0x98
Opcode(olol_transformRegion);
Opcode(olol_crossFadeRegion);
Opcode(olol_calcCoordinatesAddDirectionOffset);
Opcode(olol_resetPortraitsAndDisableSysTimer);
Opcode(olol_enableSysTimer);
@ -2981,7 +2961,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_calcNewBlockPosition);
// 0xB8
Opcode(olol_fadeScene);
Opcode(olol_crossFadeScene);
Opcode(olol_updateDrawPage2);
Opcode(olol_setMouseCursor);
Opcode(olol_characterSays);
@ -2992,7 +2972,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_getLanguage);
Opcode(olol_dummy0);
Common::Array<const TIMOpcode *> *timTable = 0;
Common::Array<const TIMOpcode*> *timTable = 0;
_timIntroOpcodes.reserve(8);
SetTimOpcodeTable(_timIntroOpcodes);

View File

@ -1129,7 +1129,7 @@ typedef Common::Functor1Mem<EMCState *, int, KyraEngine_MR> OpcodeV3;
#define Opcode(x) table->push_back(new OpcodeV3(this, &KyraEngine_MR::x))
#define OpcodeUnImpl() table->push_back(new OpcodeV3(this, 0))
void KyraEngine_MR::setupOpcodeTable() {
Common::Array<const Opcode *> *table = 0;
Common::Array<const Opcode*> *table = 0;
_opcodes.reserve(176);
SetOpcodeTable(_opcodes);

View File

@ -135,7 +135,7 @@ bool TIMInterpreter::callback(Common::IFFChunk &chunk) {
return false;
}
TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes) {
TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes) {
if (!_vm->resource()->exists(filename))
return 0;
@ -833,18 +833,6 @@ int TIMInterpreter::cmd_stopFuncNow(const uint16 *param) {
return 1;
}
int TIMInterpreter::cmd_stopAllFuncs(const uint16 *param) {
while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && !_vm->shouldQuit()) {
update();
_currentTim->clickedButton = processDialogue();
}
for (int i = 0; i < TIM::kCountFuncs; ++i)
_currentTim->func[i].ip = 0;
return -1;
}
// TODO: Consider moving to another file
#ifdef ENABLE_LOL
@ -908,9 +896,6 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2,
_animator = new TimAnimator(engine, screen_v2, system, true);
_drawPage2 = 0;
memset(_dialogueButtonString, 0, 3 * sizeof(const char *));
_dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0;
}
int TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) {
@ -978,157 +963,12 @@ void TIMInterpreter_LoL::advanceToOpcode(int opcode) {
f->nextTime = _system->getMillis();
}
void TIMInterpreter_LoL::drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {
_screen->setScreenDim(5);
if (numStr == 1 && _vm->speechEnabled()) {
_dialogueNumButtons = 0;
_dialogueButtonString[0] = _dialogueButtonString[1] = _dialogueButtonString[2] = 0;
} else {
_dialogueNumButtons = numStr;
_dialogueButtonString[0] = s1;
_dialogueButtonString[1] = s2;
_dialogueButtonString[2] = s3;
_dialogueHighlightedButton = 0;
const ScreenDim *d = _screen->getScreenDim(5);
_dialogueButtonPosY = d->sy + d->h - 9;
if (numStr == 1) {
_dialogueButtonXoffs = 0;
_dialogueButtonPosX = d->sx + d->w - 77;
} else {
_dialogueButtonXoffs = d->w / numStr;
_dialogueButtonPosX = d->sx + (_dialogueButtonXoffs >> 1) - 37;
}
drawDialogueButtons();
}
if (!_vm->shouldQuit())
_vm->removeInputTop();
}
void TIMInterpreter_LoL::drawDialogueButtons() {
int cp = _screen->setCurPage(0);
Screen::FontId of = _screen->setFont(_vm->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
int x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
if (_vm->gameFlags().use16ColorMode) {
_vm->gui_drawBox(x, (_dialogueButtonPosY & ~7) - 1, 74, 10, 0xee, 0xcc, -1);
_screen->printText(_dialogueButtonString[i], (x + 37 - (_screen->getTextWidth(_dialogueButtonString[i])) / 2) & ~3,
(_dialogueButtonPosY + 2) & ~7, _dialogueHighlightedButton == i ? 0xc1 : 0xe1, 0);
} else {
_vm->gui_drawBox(x, _dialogueButtonPosY, 74, 9, 136, 251, -1);
_screen->printText(_dialogueButtonString[i], x + 37 - (_screen->getTextWidth(_dialogueButtonString[i])) / 2,
_dialogueButtonPosY + 2, _dialogueHighlightedButton == i ? 144 : 254, 0);
}
x += _dialogueButtonXoffs;
}
_screen->setFont(of);
_screen->setCurPage(cp);
}
uint16 TIMInterpreter_LoL::processDialogue() {
int df = _dialogueHighlightedButton;
int res = 0;
int x = _dialogueButtonPosX;
int y = (_vm->gameFlags().use16ColorMode ? (_dialogueButtonPosY & ~7) - 1 : _dialogueButtonPosY);
for (int i = 0; i < _dialogueNumButtons; i++) {
Common::Point p = _vm->getMousePos();
if (_vm->posWithinRect(p.x, p.y, x, y, x + 74, y + 9)) {
_dialogueHighlightedButton = i;
break;
}
x += _dialogueButtonXoffs;
}
if (_dialogueNumButtons == 0) {
int e = _vm->checkInput(0, false) & 0xFF;
_vm->removeInputTop();
if (e) {
_vm->gui_notifyButtonListChanged();
if (e == 43 || e == 61) {
_vm->snd_stopSpeech(true);
}
}
if (_vm->snd_updateCharacterSpeech() != 2) {
res = 1;
if (!_vm->shouldQuit()) {
_vm->removeInputTop();
_vm->gui_notifyButtonListChanged();
}
}
} else {
int e = _vm->checkInput(0, false) & 0xFF;
_vm->removeInputTop();
if (e)
_vm->gui_notifyButtonListChanged();
if (e == 200 || e == 202) {
x = _dialogueButtonPosX;
for (int i = 0; i < _dialogueNumButtons; i++) {
Common::Point p = _vm->getMousePos();
if (_vm->posWithinRect(p.x, p.y, x, y, x + 74, y + 9)) {
_dialogueHighlightedButton = i;
res = _dialogueHighlightedButton + 1;
break;
}
x += _dialogueButtonXoffs;
}
} else if (e == _vm->_keyMap[Common::KEYCODE_SPACE] || e == _vm->_keyMap[Common::KEYCODE_RETURN]) {
_vm->snd_stopSpeech(true);
res = _dialogueHighlightedButton + 1;
} else if (e == _vm->_keyMap[Common::KEYCODE_LEFT] || e == _vm->_keyMap[Common::KEYCODE_DOWN]) {
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton > 0)
_dialogueHighlightedButton--;
} else if (e == _vm->_keyMap[Common::KEYCODE_RIGHT] || e == _vm->_keyMap[Common::KEYCODE_UP]) {
if (_dialogueNumButtons > 1 && _dialogueHighlightedButton < (_dialogueNumButtons - 1))
_dialogueHighlightedButton++;
}
}
if (df != _dialogueHighlightedButton)
drawDialogueButtons();
_screen->updateScreen();
if (res == 0)
return 0;
_vm->stopPortraitSpeechAnim();
if (!_vm->textEnabled() && _vm->_currentControlMode) {
_screen->setScreenDim(5);
const ScreenDim *d = _screen->getScreenDim(5);
_screen->fillRect(d->sx, d->sy + d->h - 9, d->sx + d->w - 1, d->sy + d->h - 1, d->unkA);
} else {
const ScreenDim *d = _screen->_curDim;
if (_vm->gameFlags().use16ColorMode)
_screen->fillRect(d->sx, d->sy, d->sx + d->w - 3, d->sy + d->h - 2, d->unkA);
else
_screen->fillRect(d->sx, d->sy, d->sx + d->w - 2, d->sy + d->h - 1, d->unkA);
_vm->_txt->clearDim(4);
_vm->_txt->resetDimTextPositions(4);
}
return res;
}
void TIMInterpreter_LoL::resetDialogueState(TIM *tim) {
if (!tim)
return;
tim->procFunc = 0;
tim->procParam = _dialogueNumButtons ? _dialogueNumButtons : 1;
tim->procParam = _vm->_dialogueNumButtons ? _vm->_dialogueNumButtons : 1;
tim->clickedButton = 0;
tim->dlgFunc = -1;
}
@ -1168,6 +1008,18 @@ int TIMInterpreter_LoL::execCommand(int cmd, const uint16 *param) {
return (this->*_commands[cmd].proc)(param);
}
int TIMInterpreter_LoL::cmd_stopAllFuncs(const uint16 *param) {
while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && !_vm->shouldQuit()) {
update();
_currentTim->clickedButton = _vm->processDialogue();
}
for (int i = 0; i < TIM::kCountFuncs; ++i)
_currentTim->func[i].ip = 0;
return -1;
}
int TIMInterpreter_LoL::cmd_setLoopIp(const uint16 *param) {
if (_vm->speechEnabled()) {
if (_vm->snd_updateCharacterSpeech() == 2)
@ -1201,7 +1053,7 @@ int TIMInterpreter_LoL::cmd_continueLoop(const uint16 *param) {
}
int TIMInterpreter_LoL::cmd_processDialogue(const uint16 *param) {
int res = processDialogue();
int res = _vm->processDialogue();
if (!res || !_currentTim->procParam)
return res;
@ -1238,7 +1090,7 @@ int TIMInterpreter_LoL::cmd_dialogueBox(const uint16 *param) {
}
}
drawDialogueBox(cnt, tmpStr[0], tmpStr[1], tmpStr[2]);
_vm->setupDialogueButtons(cnt, tmpStr[0], tmpStr[1], tmpStr[2]);
_vm->gui_notifyButtonListChanged();
return -3;

View File

@ -146,7 +146,7 @@ struct TIM {
uint16 *avtl;
uint8 *text;
const Common::Array<const TIMOpcode *> *opcodes;
const Common::Array<const TIMOpcode*> *opcodes;
// TODO: Get rid of this ugly HACK to allow the
// Lands of Lore outro to be working properly.
@ -159,7 +159,7 @@ public:
TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system);
virtual ~TIMInterpreter();
TIM *load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes);
TIM *load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes);
void unload(TIM *&tim) const;
bool callback(Common::IFFChunk &chunk);
@ -186,8 +186,6 @@ public:
void displayText(uint16 textId, int16 flags, uint8 color);
void setupTextPalette(uint index, int fadePalette);
virtual void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3) {}
virtual uint16 processDialogue() { return 1; }
virtual void resetDialogueState(TIM *tim) {}
int _drawPage2;
@ -255,7 +253,6 @@ protected:
int cmd_execOpcode(const uint16 *param);
int cmd_initFuncNow(const uint16 *param);
int cmd_stopFuncNow(const uint16 *param);
int cmd_stopAllFuncs(const uint16 *param);
#define cmd_return(n, v) \
int cmd_return_##n(const uint16 *){ return v; }
cmd_return( 1, 1)
@ -273,8 +270,6 @@ public:
int initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams);
int freeAnimStruct(int index);
void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
uint16 processDialogue();
void resetDialogueState(TIM *tim);
private:
@ -284,18 +279,9 @@ private:
char *getTableString(int id);
void advanceToOpcode(int opcode);
void drawDialogueButtons();
LoLEngine *_vm;
Screen_LoL *_screen;
const char *_dialogueButtonString[3];
uint16 _dialogueButtonPosX;
uint16 _dialogueButtonPosY;
int _dialogueNumButtons;
uint16 _dialogueButtonXoffs;
int _dialogueHighlightedButton;
virtual int execCommand(int cmd, const uint16 *param);
typedef int (TIMInterpreter_LoL::*CommandProc)(const uint16 *);
@ -307,6 +293,7 @@ private:
const CommandEntry *_commands;
int _commandsSize;
int cmd_stopAllFuncs(const uint16 *param);
int cmd_setLoopIp(const uint16 *param);
int cmd_continueLoop(const uint16 *param);
int cmd_processDialogue(const uint16 *param);

View File

@ -0,0 +1,140 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef ENABLE_EOB
#include "kyra/eob1.h"
#include "kyra/screen_eob.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "common/system.h"
#include "base/version.h"
namespace Kyra {
int EobEngine::mainMenu() {
int menuChoice = 4;
Screen::FontId of = _screen->_currentFont;
Common::SeekableReadStream *s = 0;
while (menuChoice >= 0 && !shouldQuit()) {
switch (menuChoice) {
case 0:
_screen->loadPalette("EOBPAL.COL", _screen->getPalette(0));
_screen->loadEobCpsFileToPage("INTRO", 0, 5, 3, 2);
_screen->setScreenPalette(_screen->getPalette(0));
_screen->_curPage = 2;
of = _screen->setFont(Screen::FID_6_FNT);
_screen->printText(gScummVMVersion, 280 - strlen(gScummVMVersion) * 6, 153, _screen->getPagePixel(2, 0, 0), 0);
_screen->setFont(of);
_screen->fillRect(0, 159, 319, 199, _screen->getPagePixel(2, 0, 0));
gui_drawBox(77, 165, 173, 29, 13, 14, 12);
gui_drawBox(76, 164, 175, 31, 13, 14, -1);
_screen->_curPage = 0;
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
menuChoice = mainMenuLoop();
break;
case 1:
// load game in progress
//
menuChoice = -1;
break;
case 2:
// create new party
menuChoice = -2;
break;
case 3:
// quit
menuChoice = -5;
break;
case 4:
// intro
_sound->loadSoundFile("SOUND");
_screen->hideMouse();
seq_playOpeningCredits();
seq_playIntro();
_screen->showMouse();
_sound->loadSoundFile("ADLIB");
menuChoice = 0;
break;
}
}
return shouldQuit() ? -5 : menuChoice;
}
int EobEngine::mainMenuLoop() {
int sel = -1;
do {
_screen->setScreenDim(28);
_gui->setupMenu(8, 0, _mainMenuStrings, -1, 0, 0);
while (sel == -1 && !shouldQuit())
sel = _gui->handleMenu(8, _mainMenuStrings, 0, -1, 0);
} while ((sel < 0 || sel > 5) && !shouldQuit());
return sel + 1;
}
void EobEngine::seq_playOpeningCredits() {
static const char *cmpList[] = { "WESTWOOD.CMP", "AND.CMP", "SSI.CMP", "PRESENT.CMP", "DAND.CMP" };
static const uint8 frameDelay[] = { 140, 50, 100, 50, 140 };
_screen->loadPalette("WESTWOOD.COL", _screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
_screen->loadBitmap(cmpList[0], 5, 3, 0);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
_sound->playTrack(1);
delay(frameDelay[0] * _tickLength);
for (int i = 1; i < 5 && !shouldQuit() && !skipFlag(); i++) {
_screen->loadBitmap(cmpList[i], 5, 3, 0);
uint32 nextFrameTimer = _system->getMillis() + frameDelay[i] * _tickLength;
_screen->crossFadeRegion(0, 50, 0, 50, 320, 102, 2, 0);
delayUntil(nextFrameTimer);
}
delay(50 * _tickLength);
}
void EobEngine::seq_playIntro() {
//_sound->playTrack(2);
}
void EobEngine::seq_playFinale() {
}
} // End of namespace Kyra
#endif // ENABLE_EOB

File diff suppressed because it is too large Load Diff

View File

@ -266,7 +266,7 @@ void KyraEngine_v1::snd_playTheme(int file, int track) {
}
void KyraEngine_v1::snd_playSoundEffect(int track, int volume) {
_sound->playSoundEffect(track);
_sound->playSoundEffect(track, volume);
}
void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) {

View File

@ -197,24 +197,9 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) {
}
}
void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
if (!_sound->sfxEnabled() || shouldQuit())
return;
if (_environmentSfx)
snd_playSoundEffect(_environmentSfx, _environmentSfxVol);
int dist = 0;
if (block) {
dist = getMonsterDistance(_currentBlock, block);
if (dist > _envSfxDistThreshold) {
_environmentSfx = 0;
return;
}
}
_environmentSfx = soundId;
_environmentSfxVol = (15 - ((block || dist < 2) ? dist : 0)) << 4;
bool LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
if (!LolEobBaseEngine::snd_processEnvironmentalSoundEffect(soundId, block))
return false;
if (block != _currentBlock) {
static const int8 blockShiftTable[] = { -32, -31, 1, 33, 32, 31, -1, -33 };
@ -231,9 +216,9 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
}
if (!soundId || _sceneUpdateRequired)
return;
return false;
snd_processEnvironmentalSoundEffect(0, 0);
return snd_processEnvironmentalSoundEffect(0, 0);
}
void LoLEngine::snd_queueEnvironmentalSoundEffect(int soundId, int block) {

1249
engines/kyra/sprites_eob.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -59,7 +59,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int animTy
for (int i = 0; i < 4; i++) {
for (int ii = 0; ii < 16; ii++) {
uint8 **of = &_monsterShapesEx[monsterIndex * 192 + i * 48 + ii * 3];
uint8 **of = &_monsterDecorationShapes[monsterIndex * 192 + i * 48 + ii * 3];
int s = (i << 4) + ii + 17;
of[0] = _screen->makeShapeCopy(p, s);
of[1] = _screen->makeShapeCopy(p, s + 1);
@ -140,9 +140,9 @@ void LoLEngine::releaseMonsterShapes(int monsterIndex) {
for (int i = 0; i < 192; i++) {
int pos = (monsterIndex * 192) + i;
if (_monsterShapesEx[pos]) {
delete[] _monsterShapesEx[pos];
_monsterShapesEx[pos] = 0;
if (_monsterDecorationShapes[pos]) {
delete[] _monsterDecorationShapes[pos];
_monsterDecorationShapes[pos] = 0;
}
}
}
@ -159,7 +159,7 @@ int LoLEngine::deleteMonstersFromBlock(int block) {
continue;
}
MonsterInPlay *m = &_monsters[i & 0x7fff];
LolMonsterInPlay *m = &_monsters[i & 0x7fff];
cnt++;
setMonsterMode(m, 14);
@ -173,7 +173,7 @@ int LoLEngine::deleteMonstersFromBlock(int block) {
return cnt;
}
void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
void LoLEngine::setMonsterMode(LolMonsterInPlay *monster, int mode) {
if (monster->mode == 13 && mode != 14)
return;
@ -210,7 +210,7 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
}
}
bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
bool LoLEngine::updateMonsterAdjustBlocks(LolMonsterInPlay *monster) {
static const uint8 dims[] = { 0, 13, 9, 3 };
if (monster->properties->flags & 8)
return true;
@ -251,7 +251,7 @@ bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
return (fx1 >= fx2) ? false : true;
}
void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
void LoLEngine::placeMonster(LolMonsterInPlay *monster, uint16 x, uint16 y) {
bool cont = true;
int t = monster->block;
if (monster->block) {
@ -329,7 +329,7 @@ int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2)
return retVal[r];
}
void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) {
void LoLEngine::setMonsterDirection(LolMonsterInPlay *monster, int dir) {
monster->direction = dir;
if (!(dir & 1) || ((monster->direction - (monster->facing << 1)) >= 2))
@ -338,7 +338,7 @@ void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) {
checkSceneUpdateNeed(monster->block);
}
void LoLEngine::monsterDropItems(MonsterInPlay *monster) {
void LoLEngine::monsterDropItems(LolMonsterInPlay *monster) {
uint16 a = monster->assignedItems;
while (a) {
uint16 b = a;
@ -503,7 +503,7 @@ int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int
uint16 b = _levelBlockProperties[block].assignedObjects;
while (b & 0x8000) {
MonsterInPlay *monster = &_monsters[b & 0x7fff];
LolMonsterInPlay *monster = &_monsters[b & 0x7fff];
if (monster->mode < 13) {
int r = checkDrawObjectSpace(x, y, monster->x, monster->y);
@ -645,7 +645,7 @@ void LoLEngine::drawBlockObjects(int blockArrayIndex) {
}
void LoLEngine::drawMonster(uint16 id) {
MonsterInPlay *m = &_monsters[id];
LolMonsterInPlay *m = &_monsters[id];
int16 flg = _monsterDirFlags[(_currentDirection << 2) + m->facing];
int curFrm = getMonsterCurFrame(m, flg & 0xffef);
uint8 *shp = 0;
@ -670,7 +670,7 @@ void LoLEngine::drawMonster(uint16 id) {
if (v == -1)
break;
uint8 *shp2 = _monsterShapesEx[m->properties->shapeIndex * 192 + v * 48 + curFrm * 3];
uint8 *shp2 = _monsterDecorationShapes[m->properties->shapeIndex * 192 + v * 48 + curFrm * 3];
if (!shp2)
continue;
@ -721,7 +721,7 @@ void LoLEngine::drawMonster(uint16 id) {
delete[] tbl;
}
int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
int LoLEngine::getMonsterCurFrame(LolMonsterInPlay *m, uint16 dirFlags) {
int tmp = 0;
switch (_monsterAnimType[m->properties->shapeIndex]) {
case 0:
@ -901,7 +901,7 @@ void LoLEngine::drawDoor(uint8 *shape, uint8 *doorPalette, int index, int unk2,
if (!shape)
return;
uint8 c = _dscDoor1[(_currentDirection << 5) + unk2];
uint8 c = _dscDoorY2[(_currentDirection << 5) + unk2];
int r = (c / 5) + 5 * _dscDimMap[index];
uint16 d = _dscShapeOvlIndex[r];
uint16 t = (index << 5) + c;
@ -1080,7 +1080,7 @@ int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int &x2, int &y2, uint
return l;
}
void LoLEngine::updateMonster(MonsterInPlay *monster) {
void LoLEngine::updateMonster(LolMonsterInPlay *monster) {
static const uint8 flags[] = { 1, 0, 1, 3, 3, 0, 0, 3, 4, 1, 0, 0, 4, 0, 0 };
if (monster->mode > 14)
return;
@ -1228,7 +1228,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
monster->flags &= 0xffef;
}
void LoLEngine::moveMonster(MonsterInPlay *monster) {
void LoLEngine::moveMonster(LolMonsterInPlay *monster) {
static const int8 turnPos[] = { 0, 2, 6, 6, 0, 2, 4, 4, 2, 2, 4, 6, 0, 0, 4, 6, 0 };
if (monster->x != monster->destX || monster->y != monster->destY) {
walkMonster(monster);
@ -1238,7 +1238,7 @@ void LoLEngine::moveMonster(MonsterInPlay *monster) {
}
}
void LoLEngine::walkMonster(MonsterInPlay *monster) {
void LoLEngine::walkMonster(LolMonsterInPlay *monster) {
if (monster->properties->flags & 0x400)
return;
@ -1253,7 +1253,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
} else {
setMonsterDirection(monster, s);
if (monster->numDistAttacks) {
if (getMonsterDistance(monster->block, _currentBlock) >= 2) {
if (getBlockDistance(monster->block, _currentBlock) >= 2) {
if (checkForPossibleDistanceAttack(monster->block, monster->direction, 3, _currentBlock) != 5) {
if (monster->distAttackTick)
return;
@ -1269,7 +1269,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
placeMonster(monster, fx, fy);
}
bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
bool LoLEngine::chasePartyWithDistanceAttacks(LolMonsterInPlay *monster) {
if (!monster->numDistAttacks)
return false;
@ -1295,7 +1295,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
int flyingObject = monster->properties->distWeapons[s];
if (flyingObject & 0xc000) {
if (getMonsterDistance(monster->block, _currentBlock) > 1) {
if (getBlockDistance(monster->block, _currentBlock) > 1) {
int type = flyingObject & 0x4000 ? 0 : 1;
flyingObject = makeItem(flyingObject & 0x3fff, 0, 0);
@ -1305,7 +1305,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
}
}
} else if (!(flyingObject & 0x2000)) {
if (getMonsterDistance(monster->block, _currentBlock) > 1)
if (getBlockDistance(monster->block, _currentBlock) > 1)
return false;
if (flyingObject == 1) {
@ -1326,7 +1326,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
} else if (flyingObject == 3) {
// shriek
for (int i = 0; i < 30; i++) {
if (getMonsterDistance(monster->block, _monsters[i].block) < 7)
if (getBlockDistance(monster->block, _monsters[i].block) < 7)
setMonsterMode(monster, 7);
}
_txt->printMessage(2, "%s", getLangString(0x401a));
@ -1347,7 +1347,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
return true;
}
void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) {
void LoLEngine::chasePartyWithCloseAttacks(LolMonsterInPlay *monster) {
if (!(monster->flags & 8)) {
int dir = calcMonsterDirection(monster->x & 0xff00, monster->y & 0xff00, _partyPosX & 0xff00, _partyPosY & 0xff00);
int x1 = _partyPosX;
@ -1389,7 +1389,7 @@ void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) {
}
}
int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
int LoLEngine::walkMonsterCalcNextStep(LolMonsterInPlay *monster) {
static const int8 walkMonsterTable1[] = { 7, -6, 5, -4, 3, -2, 1, 0 };
static const int8 walkMonsterTable2[] = { -7, 6, -5, 4, -3, 2, -1, 0 };
@ -1445,23 +1445,8 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
return -1;
}
int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
int b1x = block1 & 0x1f;
int b1y = block1 >> 5;
int b2x = block2 & 0x1f;
int b2y = block2 >> 5;
uint8 dy = ABS(b2y - b1y);
uint8 dx = ABS(b2x - b1x);
if (dx > dy)
SWAP(dx, dy);
return (dx >> 1) + dy;
}
int LoLEngine::checkForPossibleDistanceAttack(uint16 monsterBlock, int direction, int distance, uint16 curBlock) {
int mdist = getMonsterDistance(curBlock, monsterBlock);
int mdist = getBlockDistance(curBlock, monsterBlock);
if (mdist > distance)
return 5;
@ -1494,7 +1479,7 @@ int LoLEngine::checkForPossibleDistanceAttack(uint16 monsterBlock, int direction
return 5;
}
int LoLEngine::walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk) {
int LoLEngine::walkMonsterCheckDest(int x, int y, LolMonsterInPlay *monster, int unk) {
uint8 m = monster->mode;
monster->mode = 15;
@ -1512,7 +1497,7 @@ void LoLEngine::getNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY,
newY = (srcY + shiftTableY[direction]) & 0x1fff;
}
void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
void LoLEngine::rearrangeAttackingMonster(LolMonsterInPlay *monster) {
int t = (monster->direction >> 1);
uint16 mx = monster->x;
uint16 my = monster->y;
@ -1579,7 +1564,7 @@ void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
placeMonster(monster, mx, my);
}
void LoLEngine::moveStrayingMonster(MonsterInPlay *monster) {
void LoLEngine::moveStrayingMonster(LolMonsterInPlay *monster) {
int x = 0;
int y = 0;
@ -1616,13 +1601,13 @@ void LoLEngine::moveStrayingMonster(MonsterInPlay *monster) {
}
}
void LoLEngine::killMonster(MonsterInPlay *monster) {
void LoLEngine::killMonster(LolMonsterInPlay *monster) {
setMonsterMode(monster, 14);
monsterDropItems(monster);
checkSceneUpdateNeed(monster->block);
uint8 w = _levelBlockProperties[monster->block].walls[0];
uint8 f = _levelBlockProperties[monster->block].flags;
uint16 f = _levelBlockProperties[monster->block].flags;
if (_wllVmpMap[w] == 0 && _wllShapeMap[w] == 0 && !(f & 0x40) && !(monster->properties->flags & 0x1000))
_levelBlockProperties[monster->block].flags |= 0x80;

View File

@ -75,7 +75,9 @@ const IndexTable iGameTable[] = {
{ GI_KYRA1, 0 },
{ GI_KYRA2, 1 },
{ GI_KYRA3, 2 },
{ GI_LOL, 3 },
{ GI_EOB1, 3 },
{ GI_EOB2, 4 },
{ GI_LOL, 5 },
{ -1, -1 }
};
@ -257,6 +259,12 @@ bool StaticResource::init() {
{ kLolButtonData, proc(loadButtonDefs), proc(freeButtonDefs) },
#endif // ENABLE_LOL
#ifdef ENABLE_EOB
{ kEob2SequenceData, proc(loadEob2SeqData), proc(freeEob2SeqData) },
{ kEob2ShapeData, proc(loadEob2ShapeData), proc(freeEob2ShapeData) },
{ kEobNpcData, proc(loadEobNpcData), proc(freeEobNpcData) },
#endif // ENABLE_EOB
{ 0, 0, 0 }
};
#undef proc
@ -503,9 +511,9 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi
tmp_s[i].flags = stream.readUint16BE();
tmp_s[i].wsaFile = new char[14];
stream.read(const_cast<char *>(tmp_s[i].wsaFile), 14);
stream.read(const_cast<char*>(tmp_s[i].wsaFile), 14);
tmp_s[i].cpsFile = new char[14];
stream.read(const_cast<char *>(tmp_s[i].cpsFile), 14);
stream.read(const_cast<char*>(tmp_s[i].cpsFile), 14);
tmp_s[i].startupCommand = stream.readByte();
tmp_s[i].finalCommand = stream.readByte();
tmp_s[i].stringIndex1 = stream.readUint16BE();
@ -529,7 +537,7 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi
tmp_n[i].flags = stream.readUint16BE();
tmp_n[i].wsaFile = new char[14];
stream.read(const_cast<char *>(tmp_n[i].wsaFile), 14);
stream.read(const_cast<char*>(tmp_n[i].wsaFile), 14);
tmp_n[i].startframe = stream.readUint16BE();
tmp_n[i].endFrame = stream.readUint16BE();
tmp_n[i].frameDelay = stream.readUint16BE();

File diff suppressed because it is too large Load Diff

View File

@ -45,16 +45,8 @@ const FlyingObjectShape *StaticResource::loadFlyingObjectData(int id, int &entri
return (const FlyingObjectShape *)getData(id, kLolFlightShpData, entries);
}
const uint16 *StaticResource::loadRawDataBe16(int id, int &entries) {
return (const uint16 *)getData(id, kLolRawDataBe16, entries);
}
const uint32 *StaticResource::loadRawDataBe32(int id, int &entries) {
return (const uint32 *)getData(id, kLolRawDataBe32, entries);
}
const ButtonDef *StaticResource::loadButtonDefs(int id, int &entries) {
return (const ButtonDef *)getData(id, kLolButtonData, entries);
const LoLButtonDef *StaticResource::loadButtonDefs(int id, int &entries) {
return (const LoLButtonDef *)getData(id, kLolButtonData, entries);
}
bool StaticResource::loadCharData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
@ -164,34 +156,10 @@ bool StaticResource::loadFlyingObjectData(Common::SeekableReadStream &stream, vo
return true;
}
bool StaticResource::loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size) {
size = stream.size() >> 1;
uint16 *r = new uint16[size];
for (int i = 0; i < size; i++)
r[i] = stream.readUint16BE();
ptr = r;
return true;
}
bool StaticResource::loadRawDataBe32(Common::SeekableReadStream &stream, void *&ptr, int &size) {
size = stream.size() >> 2;
uint32 *r = new uint32[size];
for (int i = 0; i < size; i++)
r[i] = stream.readUint32BE();
ptr = r;
return true;
}
bool StaticResource::loadButtonDefs(Common::SeekableReadStream &stream, void *&ptr, int &size) {
size = stream.size() / 18;
ButtonDef *r = new ButtonDef[size];
LoLButtonDef *r = new LoLButtonDef[size];
for (int i = 0; i < size; i++) {
r[i].buttonflags = stream.readUint16BE();
@ -237,23 +205,8 @@ void StaticResource::freeFlyingObjectData(void *&ptr, int &size) {
size = 0;
}
void StaticResource::freeRawDataBe16(void *&ptr, int &size) {
uint16 *data = (uint16 *)ptr;
delete[] data;
ptr = 0;
size = 0;
}
void StaticResource::freeRawDataBe32(void *&ptr, int &size) {
uint32 *data = (uint32 *)ptr;
delete[] data;
ptr = 0;
size = 0;
}
void StaticResource::freeButtonDefs(void *&ptr, int &size) {
ButtonDef *d = (ButtonDef *)ptr;
LoLButtonDef *d = (LoLButtonDef *)ptr;
delete[] d;
ptr = 0;
size = 0;
@ -289,67 +242,59 @@ void LoLEngine::initStaticResource() {
if (_flags.isDemo)
return;
int tempSize;
_pakFileList = _staticres->loadStrings(kLolIngamePakFiles, _pakFileListSize);
_charDefaults = _staticres->loadCharData(kLolCharacterDefs, _charDefaultsSize);
_ingameSoundIndex = (const uint16 *)_staticres->loadRawData(kLolIngameSfxIndex, _ingameSoundIndexSize);
_musicTrackMap = _staticres->loadRawData(kLolMusicTrackMap, _musicTrackMapSize);
_ingameSoundIndex = (const uint16 *)_staticres->loadRawData(kLolIngameSfxIndex, tempSize);
_musicTrackMap = _staticres->loadRawData(kLolMusicTrackMap, tempSize);
_ingameGMSoundIndex = _staticres->loadRawData(kLolIngameGMSfxIndex, _ingameGMSoundIndexSize);
_ingameMT32SoundIndex = _staticres->loadRawData(kLolIngameMT32SfxIndex, _ingameMT32SoundIndexSize);
_ingamePCSpeakerSoundIndex = _staticres->loadRawData(kLolIngamePcSpkSfxIndex, _ingamePCSpeakerSoundIndexSize);
_spellProperties = _staticres->loadSpellData(kLolSpellProperties, _spellPropertiesSize);
_gameShapeMap = (const int8 *)_staticres->loadRawData(kLolGameShapeMap, _gameShapeMapSize);
_sceneItemOffs = (const int8 *)_staticres->loadRawData(kLolSceneItemOffs, _sceneItemOffsSize);
_charInvIndex = _staticres->loadRawData(kLolCharInvIndex, _charInvIndexSize);
_charInvDefs = _staticres->loadRawData(kLolCharInvDefs, _charInvDefsSize);
_charDefsMan = _staticres->loadRawDataBe16(kLolCharDefsMan, _charDefsManSize);
_charDefsWoman = _staticres->loadRawDataBe16(kLolCharDefsWoman, _charDefsWomanSize);
_charDefsKieran = _staticres->loadRawDataBe16(kLolCharDefsKieran, _charDefsKieranSize);
_charDefsAkshel = _staticres->loadRawDataBe16(kLolCharDefsAkshel, _charDefsAkshelSize);
_expRequirements = (const int32 *)_staticres->loadRawDataBe32(kLolExpRequirements, _expRequirementsSize);
_monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, _monsterModifiersSize);
_monsterShiftOffs = (const int8 *)_staticres->loadRawData(kLolMonsterShiftOffsets, _monsterShiftOffsSize);
_monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, _monsterDirFlagsSize);
_monsterScaleX = _staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize);
_monsterScaleY = _staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize);
_monsterScaleWH = _staticres->loadRawDataBe16(kLolMonsterScaleWH, _monsterScaleWHSize);
_inventorySlotDesc = _staticres->loadRawDataBe16(kLolInventoryDesc, _inventorySlotDescSize);
_levelShpList = _staticres->loadStrings(kLolLevelShpList, _levelShpListSize);
_levelDatList = _staticres->loadStrings(kLolLevelDatList, _levelDatListSize);
_compassDefs = _staticres->loadCompassData(kLolCompassDefs, _compassDefsSize);
_flyingItemShapes = _staticres->loadFlyingObjectData(kLolFlyingObjectShp, _flyingItemShapesSize);
_itemCost = _staticres->loadRawDataBe16(kLolItemPrices, _itemCostSize);
_stashSetupData = _staticres->loadRawData(kLolStashSetup, _stashSetupDataSize);
_spellProperties = _staticres->loadSpellData(kLolSpellProperties, tempSize);
_gameShapeMap = (const int8 *)_staticres->loadRawData(kLolGameShapeMap, tempSize);
_sceneItemOffs = (const int8 *)_staticres->loadRawData(kLolSceneItemOffs, tempSize);
_charInvIndex = _staticres->loadRawData(kLolCharInvIndex, tempSize);
_charInvDefs = _staticres->loadRawData(kLolCharInvDefs, tempSize);
_charDefsMan = _staticres->loadRawDataBe16(kLolCharDefsMan, tempSize);
_charDefsWoman = _staticres->loadRawDataBe16(kLolCharDefsWoman, tempSize);
_charDefsKieran = _staticres->loadRawDataBe16(kLolCharDefsKieran, tempSize);
_charDefsAkshel = _staticres->loadRawDataBe16(kLolCharDefsAkshel, tempSize);
_expRequirements = (const int32 *)_staticres->loadRawDataBe32(kLolExpRequirements, tempSize);
_monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, tempSize);
_monsterShiftOffs = (const int8 *)_staticres->loadRawData(kLolMonsterShiftOffsets, tempSize);
_monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, tempSize);
_monsterScaleX = _staticres->loadRawData(kLolMonsterScaleX, tempSize);
_monsterScaleY = _staticres->loadRawData(kLolMonsterScaleY, tempSize);
_monsterScaleWH = _staticres->loadRawDataBe16(kLolMonsterScaleWH, tempSize);
_inventorySlotDesc = _staticres->loadRawDataBe16(kLolInventoryDesc, tempSize);
_levelShpList = _staticres->loadStrings(kLolLevelShpList, tempSize);
_levelDatList = _staticres->loadStrings(kLolLevelDatList, tempSize);
_compassDefs = _staticres->loadCompassData(kLolCompassDefs, tempSize);
_flyingItemShapes = _staticres->loadFlyingObjectData(kLolFlyingObjectShp, tempSize);
_itemCost = _staticres->loadRawDataBe16(kLolItemPrices, tempSize);
_stashSetupData = _staticres->loadRawData(kLolStashSetup, tempSize);
_dscUnk1 = (const int8 *)_staticres->loadRawData(kLolDscUnk1, _dscUnk1Size);
_dscShapeIndex = (const int8 *)_staticres->loadRawData(kLolDscShapeIndex, _dscShapeIndexSize);
_dscOvlMap = _staticres->loadRawData(kLolDscOvlMap, _dscOvlMapSize);
_dscShapeScaleW = _staticres->loadRawDataBe16(kLolDscScaleWidthData, _dscShapeScaleWSize);
_dscShapeScaleH = _staticres->loadRawDataBe16(kLolDscScaleHeightData, _dscShapeScaleHSize);
_dscShapeX = (const int16 *)_staticres->loadRawDataBe16(kLolDscX, _dscShapeXSize);
_dscShapeY = (const int8 *)_staticres->loadRawData(kLolDscY, _dscShapeYSize);
_dscTileIndex = _staticres->loadRawData(kLolDscTileIndex, _dscTileIndexSize);
_dscUnk2 = _staticres->loadRawData(kLolDscUnk2, _dscUnk2Size);
_dscDoorShpIndex = _staticres->loadRawData(kLolDscDoorShapeIndex, _dscDoorShpIndexSize);
_dscDim1 = (const int8 *)_staticres->loadRawData(kLolDscDimData1, _dscDim1Size);
_dscDim2 = (const int8 *)_staticres->loadRawData(kLolDscDimData2, _dscDim2Size);
_dscBlockMap = _staticres->loadRawData(kLolDscBlockMap, _dscBlockMapSize);
_dscDimMap = _staticres->loadRawData(kLolDscDimMap, _dscDimMapSize);
_dscDoorMonsterScaleTable = _staticres->loadRawDataBe16(kLolDscDoorScale, _dscDoorMonsterScaleTableSize);
_dscShapeOvlIndex = _staticres->loadRawData(kLolDscOvlIndex, _dscShapeOvlIndexSize);
_dscDoor4 = _staticres->loadRawDataBe16(kLolDscDoor4, _dscDoor4Size);
_dscBlockIndex = (const int8 *)_staticres->loadRawData(kLolDscBlockIndex, _dscBlockIndexSize);
_dscDoor1 = _staticres->loadRawData(kLolDscDoor1, _dscDoor1Size);
_dscDoorMonsterX = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorX, _dscDoorMonsterXSize);
_dscDoorMonsterY = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorY, _dscDoorMonsterYSize);
_dscWalls = (const int8 *)_staticres->loadRawData(kLolDscWalls, tempSize);
_scrollXTop = _staticres->loadRawData(kLolScrollXTop, _scrollXTopSize);
_scrollYTop = _staticres->loadRawData(kLolScrollYTop, _scrollYTopSize);
_scrollXBottom = _staticres->loadRawData(kLolScrollXBottom, _scrollXBottomSize);
_scrollYBottom = _staticres->loadRawData(kLolScrollYBottom, _scrollYBottomSize);
_dscOvlMap = _staticres->loadRawData(kLolDscOvlMap, tempSize);
_dscShapeOvlIndex = _staticres->loadRawData(kLolDscOvlIndex, tempSize);
_dscShapeScaleW = _staticres->loadRawDataBe16(kLolDscScaleWidthData, tempSize);
_dscShapeScaleH = _staticres->loadRawDataBe16(kLolDscScaleHeightData, tempSize);
_dscShapeY = (const int8 *)_staticres->loadRawData(kLolBaseDscY, tempSize);
_dscDoorMonsterScaleTable = _staticres->loadRawDataBe16(kLolDscDoorScale, tempSize);
_dscDoor4 = _staticres->loadRawDataBe16(kLolDscDoor4, tempSize);
_dscDoorMonsterX = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorX, tempSize);
_dscDoorMonsterY = (const int16 *)_staticres->loadRawDataBe16(kLolDscDoorY, tempSize);
_scrollXTop = _staticres->loadRawData(kLolScrollXTop, tempSize);
_scrollYTop = _staticres->loadRawData(kLolScrollYTop, tempSize);
_scrollXBottom = _staticres->loadRawData(kLolScrollXBottom, tempSize);
_scrollYBottom = _staticres->loadRawData(kLolScrollYBottom, tempSize);
const char *const *tmpSndList = _staticres->loadStrings(kLolIngameSfxFiles, _ingameSoundListSize);
if (tmpSndList) {
_ingameSoundList = new char *[_ingameSoundListSize];
_ingameSoundList = new char*[_ingameSoundListSize];
for (int i = 0; i < _ingameSoundListSize; i++) {
_ingameSoundList[i] = new char[strlen(tmpSndList[i]) + 1];
strcpy(_ingameSoundList[i], tmpSndList[i]);
@ -357,19 +302,18 @@ void LoLEngine::initStaticResource() {
_staticres->unloadId(kLolIngameSfxFiles);
}
_buttonData = _staticres->loadButtonDefs(kLolButtonDefs, _buttonDataSize);
_buttonList1 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList1, _buttonList1Size);
_buttonList2 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList2, _buttonList2Size);
_buttonList3 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList3, _buttonList3Size);
_buttonList4 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList4, _buttonList4Size);
_buttonList5 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList5, _buttonList5Size);
_buttonList6 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList6, _buttonList6Size);
_buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList7, _buttonList7Size);
_buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList8, _buttonList8Size);
_buttonData = _staticres->loadButtonDefs(kLolButtonDefs, tempSize);
_buttonList1 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList1, tempSize);
_buttonList2 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList2, tempSize);
_buttonList3 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList3, tempSize);
_buttonList4 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList4, tempSize);
_buttonList5 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList5, tempSize);
_buttonList6 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList6, tempSize);
_buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList7, tempSize);
_buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList8, tempSize);
_autoMapStrings = _staticres->loadRawDataBe16(kLolMapStringId, _autoMapStringsSize);
_autoMapStrings = _staticres->loadRawDataBe16(kLolMapStringId, tempSize);
int tempSize;
const uint8 *tmp = _staticres->loadRawData(kLolLegendData, tempSize);
uint8 entrySize = tempSize / 12;
tempSize /= entrySize;
@ -386,13 +330,15 @@ void LoLEngine::initStaticResource() {
}
tmp = _staticres->loadRawData(kLolMapCursorOvl, tempSize);
_mapCursorOverlay = new uint8[tempSize];
memcpy(_mapCursorOverlay, tmp, tempSize);
_staticres->unloadId(kLolMapCursorOvl);
if (tmp) {
_mapCursorOverlay = new uint8[tempSize];
memcpy(_mapCursorOverlay, tmp, tempSize);
_staticres->unloadId(kLolMapCursorOvl);
}
_updateSpellBookCoords = _staticres->loadRawData(kLolSpellbookCoords, _updateSpellBookCoordsSize);
_updateSpellBookAnimData = _staticres->loadRawData(kLolSpellbookAnim, _updateSpellBookAnimDataSize);
_healShapeFrames = _staticres->loadRawData(kLolHealShapeFrames, _healShapeFramesSize);
_updateSpellBookCoords = _staticres->loadRawData(kLolSpellbookCoords, tempSize);
_updateSpellBookAnimData = _staticres->loadRawData(kLolSpellbookAnim, tempSize);
_healShapeFrames = _staticres->loadRawData(kLolHealShapeFrames, tempSize);
tmp = _staticres->loadRawData(kLolLightningDefs, tempSize);
if (tmp) {
@ -405,7 +351,7 @@ void LoLEngine::initStaticResource() {
_staticres->unloadId(kLolLightningDefs);
}
_fireBallCoords = (const int16 *)_staticres->loadRawDataBe16(kLolFireballCoords, _fireBallCoordsSize);
_fireBallCoords = (const int16*)_staticres->loadRawDataBe16(kLolFireballCoords, tempSize);
_buttonCallbacks.clear();
_buttonCallbacks.reserve(95);

649
engines/kyra/text_eob.cpp Normal file
View File

@ -0,0 +1,649 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/loleobbase.h"
#include "kyra/screen.h"
#include "kyra/timer.h"
#include "common/system.h"
namespace Kyra {
TextDisplayer_Eob::TextDisplayer_Eob(LolEobBaseEngine *engine, Screen *sScreen) : _vm(engine), _screen(sScreen),
_lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), _allowPageBreak(true),
_numCharsLeft(0), _numCharsPrinted(0), _sjisLineBreakFlag(false), _waitButtonMode(1) {
_dialogueBuffer = new char[1024];
memset(_dialogueBuffer, 0, 1024);
_currentLine = new char[85];
memset(_currentLine, 0, 85);
_textDimData = new TextDimData[_screen->screenDimTableCount()];
for (int i = 0; i < _screen->screenDimTableCount(); i++){
const ScreenDim *d = _screen->getScreenDim(i);
_textDimData[i].color1 = d->unk8;
_textDimData[i].color2 = d->unkA;
_textDimData[i].line = d->unkC;
_textDimData[i].column = d->unkE;
}
_waitButtonSpace = 0;
}
TextDisplayer_Eob::~TextDisplayer_Eob() {
delete[] _dialogueBuffer;
delete[] _currentLine;
delete[] _textDimData;
}
void TextDisplayer_Eob::setupField(int dim, bool mode) {
setPageBreakFlag();
_textDimData[dim].color2 = _vm->_bkgColor_1;
_screen->setScreenDim(dim);
if (mode)
clearCurDim();
else
resetDimTextPositions(dim);
//_textPageBreakFunc = textPageBreakMore; + 0x25
}
void TextDisplayer_Eob::resetDimTextPositions(int dim) {
_textDimData[dim].column = 0;
_textDimData[dim].line = 0;
}
void TextDisplayer_Eob::resetPageBreakString() {
if (vm()->_moreStrings)
strcpy(_pageBreakString, vm()->_moreStrings[0]);
}
void TextDisplayer_Eob::setPageBreakFlag() {
_allowPageBreak = true;
_lineCount = 0;
}
void TextDisplayer_Eob::removePageBreakFlag() {
_allowPageBreak = false;
}
void TextDisplayer_Eob::displayText(char *str, ...) {
const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98);
_printFlag = false;
_lineWidth = 0;
_numCharsLeft = 0;
_numCharsPrinted = 0;
_tempString1 = str;
_tempString2 = 0;
_currentLine[0] = 0;
memset(_ctrl, 0, 3);
char c = parseCommand();
va_list args;
va_start(args, str);
const ScreenDim *sd = _screen->_curDim;
int sdx = _screen->curDimIndex();
bool pc98PrintFlag = (isPc98 && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
uint16 charsPerLine = (sd->w << 3) / (_screen->getFontWidth() + _screen->_charWidth);
while (c) {
char a = tolower(_ctrl[1]);
if (!_tempString2 && c == '%') {
if (a == 'd') {
snprintf(_scriptParaString, 11, "%d", va_arg(args, int));
_tempString2 = _scriptParaString;
} else if (a == 's') {
_tempString2 = va_arg(args, char *);
} else {
break;
}
_ctrl[0] = _ctrl[2];
_ctrl[2] = _ctrl[1] = 0;
c = parseCommand();
}
if (isPc98) {
uint8 cu = (uint8) c;
if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0)) {
_currentLine[_numCharsLeft++] = c;
_currentLine[_numCharsLeft++] = parseCommand();
_currentLine[_numCharsLeft] = '\0';
_lineWidth += 8;
if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3))
printLine(_currentLine);
c = parseCommand();
continue;
}
}
uint16 dv = _textDimData[sdx].column / (_screen->getFontWidth() + _screen->_charWidth);
switch (c - 1) {
case 0:
printLine(_currentLine);
textPageBreak();
_numCharsPrinted = 0;
break;
case 1:
printLine(_currentLine);
_textDimData[sdx].color2 = parseCommand();
break;
case 5:
printLine(_currentLine);
_textDimData[sdx].color1 = parseCommand();
break;
case 8:
printLine(_currentLine);
dv = _textDimData[sdx].column / (_screen->getFontWidth() + _screen->_charWidth);
dv = ((dv + 8) & 0xfff8) - 1;
if (dv >= charsPerLine)
dv = 0;
_textDimData[sdx].column = (_screen->getFontWidth() + _screen->_charWidth) * dv;
break;
case 11:
_sjisLineBreakFlag=_sjisLineBreakFlag;
// TODO (UNUSED)
break;
case 12:
if (isPc98)
_sjisLineBreakFlag = true;
printLine(_currentLine);
_sjisLineBreakFlag = false;
_lineCount++;
_textDimData[sdx].column = 0;
_textDimData[sdx].line++;
break;
case 18:
_sjisLineBreakFlag=_sjisLineBreakFlag;
// TODO (UNUSED)
break;
case 23:
_sjisLineBreakFlag=_sjisLineBreakFlag;
// TODO (UNUSED)
break;
case 24:
_sjisLineBreakFlag=_sjisLineBreakFlag;
// TODO (UNUSED)
break;
case 26:
_sjisLineBreakFlag=_sjisLineBreakFlag;
// TODO (UNUSED)
break;
case 28:
_sjisLineBreakFlag=_sjisLineBreakFlag;
// TODO (UNUSED)
break;
default:
_lineWidth += (pc98PrintFlag ? 4 : _screen->getCharWidth((uint8)c));
_currentLine[_numCharsLeft++] = c;
_currentLine[_numCharsLeft] = 0;
if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3))
printLine(_currentLine);
}
c = parseCommand();
}
va_end(args);
if (_numCharsLeft)
printLine(_currentLine);
}
char TextDisplayer_Eob::parseCommand() {
if (!_ctrl[1])
readNextPara();
char res = _ctrl[1];
_ctrl[1] = _ctrl[2];
_ctrl[2] = 0;
if (!_ctrl[1])
readNextPara();
return res;
}
void TextDisplayer_Eob::readNextPara() {
char d = 0;
if (_tempString2) {
if (*_tempString2) {
d = *_tempString2++;
} else {
_tempString2 = 0;
d = _ctrl[0];
}
}
if (!d && _tempString1) {
if (*_tempString1)
d = *_tempString1++;
else
_tempString1 = 0;
}
_ctrl[1] = d;
_ctrl[2] = 0;
}
void TextDisplayer_Eob::printLine(char *str) {
const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98);
const ScreenDim *sd = _screen->_curDim;
int sdx = _screen->curDimIndex();
bool pc98PrintFlag = (isPc98 && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
int fh = (_screen->_currentFont == Screen::FID_SJIS_FNT) ? 9 : (_screen->getFontHeight() + _screen->_charOffset);
int lines = (sd->h - _screen->_charOffset) / fh;
while (_textDimData[sdx].line >= lines) {
if ((lines - _waitButtonSpace) <= _lineCount && _allowPageBreak) {
_lineCount = 0;
textPageBreak();
_numCharsPrinted = 0;
}
int h1 = ((sd->h / fh) - 1) * fh;
int h2 = sd->h - fh;
if (h2)
_screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK);
_screen->fillRect(sd->sx << 3, sd->sy + h1, ((sd->sx + sd->w) << 3) - 1, sd->sy + sd->h - 1, _textDimData[sdx].color2);
if (_textDimData[sdx].line)
_textDimData[sdx].line--;
}
int x1 = (sd->sx << 3) + _textDimData[sdx].column;
int y = sd->sy + (pc98PrintFlag ? (_textDimData[sdx].line << 3) : (fh * _textDimData[sdx].line));
int w = sd->w << 3;
int lw = _lineWidth;
int s = _numCharsLeft;
char c = 0;
if (pc98PrintFlag) {
bool ct = true;
if ((lw + _textDimData[sdx].column) > w) {
if ((lines - 1 - (_waitButtonSpace << 1)) <= _lineCount)
// cut off line to leave space for "MORE" button
w -= 80;
} else {
if (!_sjisLineBreakFlag || (_lineCount + 1 < lines - 1))
ct = false;
else
// cut off line to leave space for "MORE" button
w -= 80;
}
if (ct) {
w -= _textDimData[sdx].column;
int n2 = 0;
int n1 = (w / 4) - 1;
while (n2 < n1 && n2 < s) {
c = str[n2];
uint8 cu = (uint8) c;
if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0))
n2++;
n2++;
}
s = n2;
}
} else {
if ((lw + _textDimData[sdx].column) > w) {
if ((lines - 1) <= _lineCount && _allowPageBreak)
// cut off line to leave space for "MORE" button
w -= (10 * (_screen->getFontWidth() + _screen->_charWidth));
w -= _textDimData[sdx].column;
int n2 = 0;
int n1 = s - 1;
while (n1 > 0) {
//cut off line after last space
c = str[n1];
lw -= _screen->getCharWidth((uint8)c);
if (!n2 && lw <= w)
n2 = n1;
if (n2 && c == ' ') {
s = n1;
_printFlag = false;
break;
}
n1--;
}
if (!n1) {
if (_textDimData[sdx].column && !_printFlag) {
s = lw = 0;
_printFlag = true;
} else {
s = n2;
}
}
}
}
c = str[s];
str[s] = 0;
uint8 col = _textDimData[sdx].color1;
if (isPc98 && (sdx == 2 || sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) {
switch (_textDimData[sdx].color1) {
case 0x88:
col = 0x41;
break;
case 0x55:
col = 0x81;
break;
case 0xaa:
col = 0x21;
break;
case 0x99:
col = 0xa1;
break;
case 0x33:
col = 0xe1;
break;
case 0x18:
col = 0x61;
break;
default:
col = 1;
break;
}
_screen->printText(str, x1 & ~3, (y + 8) & ~7, col, 0);
} else {
_screen->printText(str, x1, y, col, _textDimData[sdx].color2);
}
_textDimData[sdx].column += lw;
_numCharsPrinted += strlen(str);
str[s] = c;
if (c == ' ')
s++;
if (str[s] == ' ')
s++;
uint32 len = strlen(&str[s]);
for (uint32 i = 0; i < len; i++)
str[i] = str[s + i];
str[len] = 0;
_numCharsLeft = strlen(str);
_lineWidth = pc98PrintFlag ? (_numCharsLeft << 2) : _screen->getTextWidth(str);
if (!_numCharsLeft && _textDimData[sdx].column < (sd->w << 3))
return;
_textDimData[sdx].column = 0;
_textDimData[sdx].line++;
_lineCount++;
printLine(str);
}
void TextDisplayer_Eob::printDialogueText(int stringId, const char *pageBreakString) {
strcpy(_dialogueBuffer, (const char *)(screen()->getCPagePtr(5) + READ_LE_UINT16(&screen()->getCPagePtr(5)[(stringId - 1) << 1])));
displayText(_dialogueBuffer);
if (pageBreakString) {
strcpy(_pageBreakString, pageBreakString);
displayWaitButton();
resetPageBreakString();
}
}
void TextDisplayer_Eob::printDialogueText(const char *str, bool wait) {
strcpy(_dialogueBuffer, str);
displayText(_dialogueBuffer);
if (wait)
displayWaitButton();
}
void TextDisplayer_Eob::printMessage(const char *str, int textColor, ...) {
int tc = _textDimData[screen()->curDimIndex()].color1;
if (textColor != -1)
_textDimData[screen()->curDimIndex()].color1 = textColor;
va_list args;
va_start(args, textColor);
vsnprintf(_dialogueBuffer, 240, str, args);
va_end(args);
displayText(_dialogueBuffer);
//if (textColor != -1)
_textDimData[screen()->curDimIndex()].color1 = tc;
if (!screen()->_curPage)
screen()->updateScreen();
}
int TextDisplayer_Eob::clearDim(int dim) {
int res = screen()->curDimIndex();
screen()->setScreenDim(dim);
_textDimData[dim].color1 = screen()->_curDim->unk8;
_textDimData[dim].color2 = vm()->game() == GI_LOL ? screen()->_curDim->unkA : vm()->_bkgColor_1;
clearCurDim();
return res;
}
void TextDisplayer_Eob::clearCurDim() {
int d = screen()->curDimIndex();
const ScreenDim *tmp = screen()->getScreenDim(d);
if (vm()->gameFlags().use16ColorMode) {
screen()->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 2, (tmp->sy + tmp->h) - 2, _textDimData[d].color2);
} else
screen()->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, _textDimData[d].color2);
_lineCount = 0;
_textDimData[d].column = _textDimData[d].line = 0;
}
void TextDisplayer_Eob::textPageBreak() {
if (vm()->game() != GI_LOL)
SWAP(vm()->_dialogueButtonLabelCol1, vm()->_dialogueButtonLabelCol2);
int cp = _screen->setCurPage(0);
Screen::FontId cf = screen()->setFont(vm()->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
vm()->_timer->pauseSingleTimer(11, true);
vm()->_fadeText = false;
int resetPortraitAfterSpeechAnim = 0;
int updatePortraitSpeechAnimDuration = 0;
if (vm()->_updateCharNum != -1) {
resetPortraitAfterSpeechAnim = vm()->_resetPortraitAfterSpeechAnim;
vm()->_resetPortraitAfterSpeechAnim = 0;
updatePortraitSpeechAnimDuration = vm()->_updatePortraitSpeechAnimDuration;
if (vm()->_updatePortraitSpeechAnimDuration > 36)
vm()->_updatePortraitSpeechAnimDuration = 36;
}
uint32 speechPartTime = 0;
if (vm()->speechEnabled() && vm()->_activeVoiceFileTotalTime && _numCharsTotal)
speechPartTime = vm()->_system->getMillis() + ((_numCharsPrinted * vm()->_activeVoiceFileTotalTime) / _numCharsTotal);
const ScreenDim *dim = screen()->getScreenDim(screen()->curDimIndex());
int x = ((dim->sx + dim->w) << 3) - (_vm->_dialogueButtonW + 3);
int y = 0;
if (vm()->_needSceneRestore && (vm()->_updateFlags & 2)) {
if (vm()->_currentControlMode || !(vm()->_updateFlags & 2)) {
y = dim->sy + dim->h - 5;
} else {
x += 6;
y = dim->sy + dim->h - 2;
}
} else if (vm()->game() == GI_LOL) {
y = dim->sy + dim->h - 10;
} else {
y = _waitButtonMode ? 162 : 189;
x = _waitButtonMode ? 76 : 221;
}
if (vm()->gameFlags().use16ColorMode) {
vm()->gui_drawBox(x + 8, (y & ~7) - 1, 66, 10, 0xee, 0xcc, -1);
screen()->printText(_pageBreakString, (x + 37 - (strlen(_pageBreakString) << 1) + 4) & ~3, (y + 2) & ~7, 0xc1, 0);
} else {
vm()->gui_drawBox(x, y, vm()->_dialogueButtonW, vm()->_dialogueButtonH, vm()->_color1_1, vm()->_color2_1, vm()->_bkgColor_1);
screen()->printText(_pageBreakString, x + (vm()->_dialogueButtonW >> 1) - (vm()->screen()->getTextWidth(_pageBreakString) >> 1), y + 2, vm()->_dialogueButtonLabelCol1, 0);
}
vm()->removeInputTop();
bool loop = true;
bool target = false;
do {
int inputFlag = vm()->checkInput(0, false) & 0xFF;
vm()->removeInputTop();
while (!inputFlag) {
vm()->update();
if (vm()->speechEnabled()) {
if (((vm()->_system->getMillis() > speechPartTime) || (vm()->snd_updateCharacterSpeech() != 2)) && speechPartTime) {
loop = false;
inputFlag = vm()->_keyMap[Common::KEYCODE_RETURN];
break;
}
}
inputFlag = vm()->checkInput(0, false) & 0xFF;
vm()->removeInputTop();
}
vm()->gui_notifyButtonListChanged();
if (inputFlag == vm()->_keyMap[Common::KEYCODE_SPACE] || inputFlag == vm()->_keyMap[Common::KEYCODE_RETURN]) {
loop = false;
} else if (inputFlag == 199 || inputFlag == 201) {
if (vm()->posWithinRect(vm()->_mouseX, vm()->_mouseY, x, y, x + _vm->_dialogueButtonW, y + 9)) {
if (_vm->game() == GI_LOL)
target = true;
else
loop = false;
}
} else if (inputFlag == 200 || inputFlag == 202) {
if (target)
loop = false;
}
} while (loop);
if (vm()->gameFlags().use16ColorMode)
screen()->fillRect(x + 8, y, x + 57, y + 9, _textDimData[screen()->curDimIndex()].color2);
else
screen()->fillRect(x, y, x + 73, y + 8, _textDimData[screen()->curDimIndex()].color2);
clearCurDim();
vm()->_timer->pauseSingleTimer(11, false);
if (vm()->_updateCharNum != -1) {
vm()->_resetPortraitAfterSpeechAnim = resetPortraitAfterSpeechAnim;
if (updatePortraitSpeechAnimDuration > 36)
updatePortraitSpeechAnimDuration -= 36;
else
updatePortraitSpeechAnimDuration >>= 1;
vm()->_updatePortraitSpeechAnimDuration = updatePortraitSpeechAnimDuration;
}
screen()->setFont(cf);
screen()->setCurPage(cp);
if (vm()->game() != GI_LOL)
SWAP(vm()->_dialogueButtonLabelCol1, vm()->_dialogueButtonLabelCol2);
vm()->removeInputTop();
}
void TextDisplayer_Eob::displayWaitButton() {
vm()->_dialogueNumButtons = 1;
vm()->_dialogueButtonString[0] = _pageBreakString;
vm()->_dialogueButtonString[1] = 0;
vm()->_dialogueButtonString[2] = 0;
vm()->_dialogueHighlightedButton = 0;
static const uint16 posX[] = { 221, 76 };
static const uint8 posY[] = { 189, 162 };
vm()->_dialogueButtonPosX = &posX[_waitButtonMode];
vm()->_dialogueButtonPosY = &posY[_waitButtonMode];
vm()->_dialogueButtonYoffs = 0;
SWAP(_vm->_dialogueButtonLabelCol1, _vm->_dialogueButtonLabelCol2);
vm()->drawDialogueButtons();
if (!vm()->shouldQuit())
vm()->removeInputTop();
while (!vm()->processDialogue() && !vm()->shouldQuit()) {}
SWAP(_vm->_dialogueButtonLabelCol1, _vm->_dialogueButtonLabelCol2);
}
} // End of namespace Kyra
#endif // (ENABLE_EOB || ENABLE_LOL)

112
engines/kyra/text_eob.h Normal file
View File

@ -0,0 +1,112 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are to numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#ifndef KYRA_TEXT_EOB_H
#define KYRA_TEXT_EOB_H
#include "common/scummsys.h"
namespace Kyra {
class Screen;
class LolEobBaseEngine;
class TextDisplayer_Eob {
public:
TextDisplayer_Eob(LolEobBaseEngine *engine, Screen *sScreen);
virtual ~TextDisplayer_Eob();
virtual void setupField(int dim, bool mode);
void printDialogueText(int stringId, const char *pageBreakString);
void printDialogueText(const char *str, bool wait = false);
void printMessage(const char *str, int textColor = -1, ...);
int clearDim(int dim);
void clearCurDim();
void resetDimTextPositions(int dim);
void resetPageBreakString();
void setPageBreakFlag();
void removePageBreakFlag();
void allowPageBreak(bool mode) { _allowPageBreak = mode; }
void setWaitButtonMode(int mode) { _waitButtonMode = mode; }
int lineCount() { return _lineCount; }
protected:
virtual LolEobBaseEngine *vm() { return _vm; }
virtual Screen *screen() { return _screen; }
void displayText(char *str, ...);
char parseCommand();
void readNextPara();
void printLine(char *str);
virtual void textPageBreak();
void displayWaitButton();
char *_dialogueBuffer;
char *_tempString1;
char *_tempString2;
char *_currentLine;
char _ctrl[3];
uint16 _lineWidth;
uint32 _numCharsTotal;
uint32 _numCharsLeft;
uint32 _numCharsPrinted;
bool _printFlag;
bool _sjisLineBreakFlag;
char _pageBreakString[20];
char _scriptParaString[11];
int _lineCount;
bool _allowPageBreak;
int _waitButtonSpace;
int _waitButtonMode;
static const char _pageBreakDefault[3][5];
struct TextDimData {
uint8 color1;
uint8 color2;
uint16 column;
uint8 line;
};
TextDimData *_textDimData;
private:
LolEobBaseEngine *_vm;
Screen *_screen;
};
} // End of namespace Kyra
#endif
#endif // ENABLE_EOB || ENABLE_LOL

View File

@ -32,36 +32,18 @@
namespace Kyra {
TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen),
_scriptTextParameter(0), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0),
_numCharsLeft(0), _numCharsPrinted(0), _sjisLineBreakFlag(false) {
TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *engine, Screen_LoL *screenLoL) : TextDisplayer_Eob(engine, engine->screen()),
_vm(engine), _screen(screenLoL), _scriptTextParameter(0) {
memset(_stringParameters, 0, 15 * sizeof(char *));
_buffer = new char[600];
memset(_buffer, 0, 600);
_dialogueBuffer = new char[1024];
memset(_dialogueBuffer, 0, 1024);
_currentLine = new char[85];
memset(_currentLine, 0, 85);
_textDimData = new TextDimData[_screen->screenDimTableCount()];
for (int i = 0; i < _screen->screenDimTableCount(); i++){
const ScreenDim *d = _screen->getScreenDim(i);
_textDimData[i].color1 = d->unk8;
_textDimData[i].color2 = d->unkA;
_textDimData[i].line = d->unkC;
_textDimData[i].column = d->unkE;
}
_waitButtonSpace = 0;
}
TextDisplayer_LoL::~TextDisplayer_LoL() {
delete[] _buffer;
delete[] _dialogueBuffer;
delete[] _currentLine;
delete[] _textDimData;
}
void TextDisplayer_LoL::setupField(bool mode) {
@ -151,20 +133,6 @@ void TextDisplayer_LoL::expandField() {
}
}
int TextDisplayer_LoL::clearDim(int dim) {
int res = _screen->curDimIndex();
_screen->setScreenDim(dim);
_textDimData[dim].color1 = _screen->_curDim->unk8;
_textDimData[dim].color2 = _screen->_curDim->unkA;
clearCurDim();
return res;
}
void TextDisplayer_LoL::resetDimTextPositions(int dim) {
_textDimData[dim].column = 0;
_textDimData[dim].line = 0;
}
void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) {
int oldDim = 0;
@ -201,10 +169,9 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script,
displayText(_dialogueBuffer);
_screen->setScreenDim(oldDim);
_lineCount = 0;
_screen->setCurPage(cp);
_screen->setFont(of);
_lineCount = 0;
_vm->_fadeText = false;
}
@ -366,465 +333,17 @@ void TextDisplayer_LoL::preprocessString(char *str, EMCState *script, const uint
*dst = 0;
}
void TextDisplayer_LoL::displayText(char *str, ...) {
const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98);
_printFlag = false;
_lineWidth = 0;
_numCharsLeft = 0;
_numCharsPrinted = 0;
_tempString1 = str;
_tempString2 = 0;
_currentLine[0] = 0;
memset(_ctrl, 0, 3);
char c = parseCommand();
va_list args;
va_start(args, str);
const ScreenDim *sd = _screen->_curDim;
int sdx = _screen->curDimIndex();
bool pc98PrintFlag = (isPc98 && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
uint16 charsPerLine = (sd->w << 3) / (_screen->getFontWidth() + _screen->_charWidth);
while (c) {
char a = tolower(_ctrl[1]);
if (!_tempString2 && c == '%') {
if (a == 'd') {
snprintf(_scriptParaString, 11, "%d", va_arg(args, int));
_tempString2 = _scriptParaString;
} else if (a == 's') {
_tempString2 = va_arg(args, char *);
} else {
break;
}
_ctrl[0] = _ctrl[2];
_ctrl[2] = _ctrl[1] = 0;
c = parseCommand();
}
if (isPc98) {
uint8 cu = (uint8) c;
if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0)) {
_currentLine[_numCharsLeft++] = c;
_currentLine[_numCharsLeft++] = parseCommand();
_currentLine[_numCharsLeft] = '\0';
_lineWidth += 8;
if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3))
printLine(_currentLine);
c = parseCommand();
continue;
}
}
uint16 dv = _textDimData[sdx].column / (_screen->getFontWidth() + _screen->_charWidth);
switch (c - 1) {
case 0:
printLine(_currentLine);
textPageBreak();
_numCharsPrinted = 0;
break;
case 1:
printLine(_currentLine);
_textDimData[sdx].color2 = parseCommand();
break;
case 5:
printLine(_currentLine);
_textDimData[sdx].color1 = parseCommand();
break;
case 8:
printLine(_currentLine);
dv = _textDimData[sdx].column / (_screen->getFontWidth() + _screen->_charWidth);
dv = ((dv + 8) & 0xfff8) - 1;
if (dv >= charsPerLine)
dv = 0;
_textDimData[sdx].column = (_screen->getFontWidth() + _screen->_charWidth) * dv;
break;
case 11:
// TODO (UNUSED)
break;
case 12:
if (isPc98)
_sjisLineBreakFlag = true;
printLine(_currentLine);
_sjisLineBreakFlag = false;
_lineCount++;
_textDimData[sdx].column = 0;
_textDimData[sdx].line++;
break;
case 18:
// TODO (UNUSED)
break;
case 23:
// TODO (UNUSED)
break;
case 24:
// TODO (UNUSED)
break;
case 26:
// TODO (UNUSED)
break;
case 28:
// TODO (UNUSED)
break;
default:
_lineWidth += (pc98PrintFlag ? 4 : _screen->getCharWidth((uint8)c));
_currentLine[_numCharsLeft++] = c;
_currentLine[_numCharsLeft] = 0;
if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3))
printLine(_currentLine);
}
c = parseCommand();
}
va_end(args);
if (_numCharsLeft)
printLine(_currentLine);
LolEobBaseEngine *TextDisplayer_LoL::vm() {
return _vm;
}
char TextDisplayer_LoL::parseCommand() {
if (!_ctrl[1])
readNextPara();
char res = _ctrl[1];
_ctrl[1] = _ctrl[2];
_ctrl[2] = 0;
if (!_ctrl[1])
readNextPara();
return res;
}
void TextDisplayer_LoL::readNextPara() {
char d = 0;
if (_tempString2) {
if (*_tempString2) {
d = *_tempString2++;
} else {
_tempString2 = 0;
d = _ctrl[0];
}
}
if (!d && _tempString1) {
if (*_tempString1)
d = *_tempString1++;
else
_tempString1 = 0;
}
_ctrl[1] = d;
_ctrl[2] = 0;
}
void TextDisplayer_LoL::printLine(char *str) {
const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98);
const ScreenDim *sd = _screen->_curDim;
int sdx = _screen->curDimIndex();
bool pc98PrintFlag = (isPc98 && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false;
int fh = (_screen->_currentFont == Screen::FID_SJIS_FNT) ? 9 : (_screen->getFontHeight() + _screen->_charOffset);
int lines = (sd->h - _screen->_charOffset) / fh;
while (_textDimData[sdx].line >= lines) {
if (lines <= _lineCount) {
_lineCount = 0;
textPageBreak();
_numCharsPrinted = 0;
}
int h1 = ((sd->h / fh) - 1) * fh;
int h2 = sd->h - fh;
if (h2)
_screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK);
_screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _textDimData[sdx].color2);
if (_textDimData[sdx].line)
_textDimData[sdx].line--;
}
int x1 = (sd->sx << 3) + _textDimData[sdx].column;
int y = sd->sy + (pc98PrintFlag ? (_textDimData[sdx].line << 3) : (fh * _textDimData[sdx].line));
int w = sd->w << 3;
int lw = _lineWidth;
int s = _numCharsLeft;
char c = 0;
if (pc98PrintFlag) {
bool ct = true;
if ((lw + _textDimData[sdx].column) > w) {
if ((lines - 1) <= _lineCount)
// cut off line to leave space for "MORE" button
w -= 80;
} else {
if (!_sjisLineBreakFlag || (_lineCount + 1 < lines - 1))
ct = false;
else
// cut off line to leave space for "MORE" button
w -= 80;
}
if (ct) {
w -= _textDimData[sdx].column;
int n2 = 0;
int n1 = (w / 4) - 1;
while (n2 < n1 && n2 < s) {
c = str[n2];
uint8 cu = (uint8) c;
if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0))
n2++;
n2++;
}
s = n2;
}
} else {
if ((lw + _textDimData[sdx].column) > w) {
if ((lines - 1) <= _lineCount)
// cut off line to leave space for "MORE" button
w -= (10 * (_screen->getFontWidth() + _screen->_charWidth));
w -= _textDimData[sdx].column;
int n2 = 0;
int n1 = s - 1;
while (n1 > 0) {
//cut off line after last space
c = str[n1];
lw -= _screen->getCharWidth((uint8)c);
if (!n2 && lw <= w)
n2 = n1;
if (n2 && c == ' ') {
s = n1;
_printFlag = false;
break;
}
n1--;
}
if (!n1) {
if (_textDimData[sdx].column && !_printFlag) {
s = lw = 0;
_printFlag = true;
} else {
s = n2;
}
}
}
}
c = str[s];
str[s] = 0;
uint8 col = _textDimData[sdx].color1;
if (isPc98 && (sdx == 2 || sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) {
switch (_textDimData[sdx].color1) {
case 0x88:
col = 0x41;
break;
case 0x55:
col = 0x81;
break;
case 0xaa:
col = 0x21;
break;
case 0x99:
col = 0xa1;
break;
case 0x33:
col = 0xe1;
break;
case 0x18:
col = 0x61;
break;
default:
col = 1;
break;
}
_screen->printText(str, x1 & ~3, (y + 8) & ~7, col, 0);
} else {
_screen->printText(str, x1, y, col, _textDimData[sdx].color2);
}
_textDimData[sdx].column += lw;
_numCharsPrinted += strlen(str);
str[s] = c;
if (c == ' ')
s++;
if (str[s] == ' ')
s++;
uint32 len = strlen(&str[s]);
for (uint32 i = 0; i < len; i++)
str[i] = str[s + i];
str[len] = 0;
_numCharsLeft = strlen(str);
_lineWidth = pc98PrintFlag ? (_numCharsLeft << 2) : _screen->getTextWidth(str);
if (!_numCharsLeft && _textDimData[sdx].column < (sd->w << 3))
return;
_textDimData[sdx].column = 0;
_textDimData[sdx].line++;
_lineCount++;
printLine(str);
Screen *TextDisplayer_LoL::screen() {
return _screen;
}
void TextDisplayer_LoL::textPageBreak() {
int cp = _screen->setCurPage(0);
Screen::FontId cf = _screen->setFont(_vm->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT);
_vm->_timer->pauseSingleTimer(11, true);
_vm->_fadeText = false;
int resetPortraitAfterSpeechAnim = 0;
int updatePortraitSpeechAnimDuration = 0;
if (_vm->_updateCharNum != -1) {
resetPortraitAfterSpeechAnim = _vm->_resetPortraitAfterSpeechAnim;
_vm->_resetPortraitAfterSpeechAnim = 0;
updatePortraitSpeechAnimDuration = _vm->_updatePortraitSpeechAnimDuration;
if (_vm->_updatePortraitSpeechAnimDuration > 36)
_vm->_updatePortraitSpeechAnimDuration = 36;
}
uint32 speechPartTime = 0;
if (_vm->speechEnabled() && _vm->_activeVoiceFileTotalTime && _numCharsTotal)
speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numCharsTotal);
const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex());
int x = ((dim->sx + dim->w) << 3) - 77;
int y = 0;
if (_vm->_needSceneRestore && (_vm->_updateFlags & 2)) {
if (_vm->_currentControlMode || !(_vm->_updateFlags & 2)) {
y = dim->sy + dim->h - 5;
} else {
x += 6;
y = dim->sy + dim->h - 2;
}
} else {
y = dim->sy + dim->h - 10;
}
char *txt = _vm->getLangString(0x4073);
if (_vm->gameFlags().use16ColorMode) {
_vm->gui_drawBox(x + 8, (y & ~7) - 1, 66, 10, 0xee, 0xcc, -1);
_vm->_screen->printText(txt, (x + 37 - (strlen(txt) << 1) + 4) & ~3, (y + 2) & ~7, 0xc1, 0);
} else {
_vm->gui_drawBox(x, y, 74, 9, 136, 251, -1);
_vm->_screen->printText(txt, x + 37 - (_vm->_screen->getTextWidth(txt) >> 1), y + 2, 144, 0);
}
_vm->removeInputTop();
bool loop = true;
bool target = false;
do {
int inputFlag = _vm->checkInput(0, false) & 0xFF;
_vm->removeInputTop();
while (!inputFlag) {
_vm->update();
if (_vm->speechEnabled()) {
if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_updateCharacterSpeech() != 2)) && speechPartTime) {
loop = false;
inputFlag = _vm->_keyMap[Common::KEYCODE_RETURN];
break;
}
}
inputFlag = _vm->checkInput(0, false) & 0xFF;
_vm->removeInputTop();
}
_vm->gui_notifyButtonListChanged();
if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
loop = false;
} else if (inputFlag == 199 || inputFlag == 201) {
if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, y, x + 74, y + 9))
target = true;
} else if (inputFlag == 200 || inputFlag == 202) {
if (target)
loop = false;
}
} while (loop);
if (_vm->gameFlags().use16ColorMode)
_screen->fillRect(x + 8, y, x + 57, y + 9, _textDimData[_screen->curDimIndex()].color2);
else
_screen->fillRect(x, y, x + 73, y + 8, _textDimData[_screen->curDimIndex()].color2);
clearCurDim();
_vm->_timer->pauseSingleTimer(11, false);
if (_vm->_updateCharNum != -1) {
_vm->_resetPortraitAfterSpeechAnim = resetPortraitAfterSpeechAnim;
if (updatePortraitSpeechAnimDuration > 36)
updatePortraitSpeechAnimDuration -= 36;
else
updatePortraitSpeechAnimDuration >>= 1;
_vm->_updatePortraitSpeechAnimDuration = updatePortraitSpeechAnimDuration;
}
_screen->setFont(cf);
_screen->setCurPage(cp);
_vm->removeInputTop();
}
void TextDisplayer_LoL::clearCurDim() {
int d = _screen->curDimIndex();
const ScreenDim *tmp = _screen->getScreenDim(d);
if (_vm->gameFlags().use16ColorMode) {
_screen->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 2, (tmp->sy + tmp->h) - 2, _textDimData[d].color2);
} else
_screen->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, _textDimData[d].color2);
_lineCount = 0;
_textDimData[d].column = _textDimData[d].line = 0;
strcpy(_pageBreakString, _vm->getLangString(0x4073));
TextDisplayer_Eob::textPageBreak();
}
} // End of namespace Kyra

View File

@ -20,80 +20,52 @@
*
*/
#ifdef ENABLE_LOL
#ifndef KYRA_TEXT_LOL_H
#define KYRA_TEXT_LOL_H
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/text_eob.h"
#endif
#include "common/scummsys.h"
#ifdef ENABLE_LOL
namespace Kyra {
class Screen_LoL;
class LoLEngine;
struct EMCState;
class TextDisplayer_LoL {
friend class LoLEngine;
class TextDisplayer_LoL : public TextDisplayer_Eob {
public:
TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen);
TextDisplayer_LoL(LoLEngine *engine, Screen_LoL *screenLoL);
~TextDisplayer_LoL();
void setupField(bool mode);
void expandField();
int clearDim(int dim);
void resetDimTextPositions(int dim);
void printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
void printMessage(uint16 type, const char *str, ...) GCC_PRINTF(3, 4);
int16 _scriptTextParameter;
private:
void displayText(char *str, ...);
char parseCommand();
void readNextPara();
void printLine(char *str);
LolEobBaseEngine *vm();
Screen *screen();
void preprocessString(char *str, EMCState *script, const uint16 *paramList, int16 paramIndex);
void textPageBreak();
void clearCurDim();
char *_stringParameters[15];
char *_buffer;
char *_dialogueBuffer;
char *_tempString1;
char *_tempString2;
char *_currentLine;
char _ctrl[3];
char _scriptParaString[11];
uint16 _lineWidth;
int _lineCount;
uint32 _numCharsTotal;
uint32 _numCharsLeft;
uint32 _numCharsPrinted;
bool _printFlag;
bool _sjisLineBreakFlag;
LoLEngine *_vm;
Screen_LoL *_screen;
struct TextDimData {
uint8 color1;
uint8 color2;
uint16 column;
uint8 line;
};
TextDimData *_textDimData;
};
} // End of namespace Kyra
#endif // ENABLE_LOL
#endif
#endif // ENABLE_LOL

View File

@ -217,7 +217,7 @@ void TimerManager::pauseSingleTimer(uint8 id, bool p) {
bool TimerManager::isEnabled(uint8 id) const {
CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
if (timer != _timers.end())
return (timer->enabled == 1);
return (timer->enabled & 1);
warning("TimerManager::isEnabled: No timer %d", id);
return false;

378
engines/kyra/timer_eob.cpp Normal file
View File

@ -0,0 +1,378 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
#include "kyra/eobcommon.h"
#include "kyra/timer.h"
#include "common/system.h"
namespace Kyra {
void LolEobBaseEngine::enableSysTimer(int sysTimer) {
if (sysTimer != 2)
return;
for (int i = 0; i < getNumClock2Timers(); i++)
_timer->pauseSingleTimer(getClock2Timer(i), false);
}
void LolEobBaseEngine::disableSysTimer(int sysTimer) {
if (sysTimer != 2)
return;
for (int i = 0; i < getNumClock2Timers(); i++)
_timer->pauseSingleTimer(getClock2Timer(i), true);
}
void LolEobBaseEngine::enableTimer(int id) {
_timer->enable(id);
_timer->setCountdown(id, _timer->getDelay(id));
}
void LolEobBaseEngine::timerProcessDoors(int timerNum) {
for (int i = 0; i < 3; i++) {
uint16 b = _openDoorState[i].block;
if (!b)
continue;
int v = _openDoorState[i].state;
int c = _openDoorState[i].wall;
_levelBlockProperties[b].walls[c] += v;
_levelBlockProperties[b].walls[c ^ 2] += v;
int snd = 3;
int flg = _wllWallFlags[_levelBlockProperties[b].walls[c]];
if (flg & 0x20)
snd = 5;
else if (v == -1)
snd = 4;
if (_flags.gameID == GI_LOL) {
if (!(_updateFlags & 1)) {
snd_processEnvironmentalSoundEffect(snd + 28, b);
if (!checkSceneUpdateNeed(b))
updateEnvironmentalSfx(0);
}
} else {
checkSceneUpdateNeed(b);
updateEnvironmentalSfx(snd);
}
if (flg & 0x30)
_openDoorState[i].block = 0;
}
}
} // namespace Kyra
#endif
#ifdef ENABLE_EOB
namespace Kyra {
#define TimerV2(x) new Common::Functor1Mem<int, void, EobCoreEngine>(this, &EobCoreEngine::x)
void EobCoreEngine::setupTimers() {
_timer->addTimer(0, TimerV2(timerProcessCharacterExchange), 9, false);
_timer->addTimer(1, TimerV2(timerProcessFlyingObjects), 3, true);
_timer->addTimer(0x20, TimerV2(timerProcessMonsters), 20, true);
_timer->addTimer(0x21, TimerV2(timerProcessMonsters), 20, true);
_timer->addTimer(0x22, TimerV2(timerProcessMonsters), 20, true);
_timer->addTimer(0x23, TimerV2(timerProcessMonsters), 20, true);
_timer->setNextRun(0x21, _system->getMillis() + 7 * _tickLength);
_timer->setNextRun(0x22, _system->getMillis() + 14 * _tickLength);
_timer->setNextRun(0x23, _system->getMillis() + 14 * _tickLength);
_timer->addTimer(0x30, TimerV2(timerSpecialCharacterUpdate), 50, false);
_timer->addTimer(0x31, TimerV2(timerSpecialCharacterUpdate), 50, false);
_timer->addTimer(0x32, TimerV2(timerSpecialCharacterUpdate), 50, false);
_timer->addTimer(0x33, TimerV2(timerSpecialCharacterUpdate), 50, false);
_timer->addTimer(0x34, TimerV2(timerSpecialCharacterUpdate), 50, false);
_timer->addTimer(0x35, TimerV2(timerSpecialCharacterUpdate), 50, false);
_timer->addTimer(4, TimerV2(timerProcessDoors), 5, true);
_timer->addTimer(5, TimerV2(timerUpdateTeleporters), 10, true);
_timer->addTimer(6, TimerV2(timerUpdateFoodStatus), 1080, true);
_timer->addTimer(7, TimerV2(timerUpdateMonsterIdleAnim), 25, true);
}
void EobCoreEngine::setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer) {
uint32 ntime = _system->getMillis() + countdown * _tickLength;
uint8 timerId = 0x30 | (charIndex & 0x0f);
EobCharacter *c = &_characters[charIndex];
if (!_timer->isEnabled(timerId)) {
c->timers[0] = ntime;
c->events[0] = evnt;
_timer->setCountdown(timerId, countdown);
enableTimer(timerId);
return;
}
if (ntime < _timer->getNextRun(timerId))
_timer->setNextRun(timerId, ntime);
if (updateExistingTimer) {
bool br = false;
int d = -1;
for (int i = 0; i < 10 && br == false; i++) {
if (d == -1 && !c->timers[i])
d = i;
if (!br && c->events[i] == evnt) {
d = i;
br = true;
}
}
c->timers[d] = ntime;
c->events[d] = evnt;
} else {
for (int i = 0; i < 10; i++) {
if (c->timers[i])
continue;
c->timers[i] = ntime;
c->events[i] = evnt;
return;
}
}
}
void EobCoreEngine::deleteCharEventTimer(int charIndex, int evnt) {
EobCharacter *c = &_characters[charIndex];
for (int i = 0; i < 10; i++) {
if (c->events[i] == evnt) {
c->events[i] = 0;
c->timers[i] = 0;
}
}
setupCharacterTimers();
}
void EobCoreEngine::setupCharacterTimers() {
for (int i = 0; i < 6; i++) {
EobCharacter *c = &_characters[i];
if (!testCharacter(i, 1))
continue;
uint32 nextTimer = 0xffffffff;
for (int ii = 0; ii < 10; ii++) {
if (c->timers[ii] < nextTimer)
nextTimer = c->timers[ii];
}
uint32 ctime = _system->getMillis();
if (nextTimer == 0xffffffff)
_timer->disable(0x30 | i);
else {
enableTimer(0x30 | i);
_timer->setCountdown(0x30 | i, (nextTimer - ctime) / _tickLength);
}
}
}
void EobCoreEngine::timerProcessCharacterExchange(int timerNum) {
_charExchangeSwap ^= 1;
if (_charExchangeSwap) {
int index = _exchangeCharacterId;
_exchangeCharacterId = -1;
gui_drawCharPortraitWithStats(index);
_exchangeCharacterId = index;
} else {
gui_drawCharPortraitWithStats(_exchangeCharacterId);
}
}
void EobCoreEngine::timerProcessFlyingObjects(int timerNum) {
static const uint8 dirPosIndex[] = { 0x82, 0x83, 0x00, 0x01, 0x01, 0x80, 0x03, 0x82, 0x02, 0x03, 0x80, 0x81, 0x81, 0x00, 0x83, 0x02 };
for (int i = 0; i < 10; i++) {
EobFlyingObject *fo = &_flyingObjects[i];
if (!fo->enable)
continue;
bool endFlight = fo->distance ? false : true;
uint8 pos = dirPosIndex[(fo->direction << 2) + (fo->curPos & 3)];
uint16 bl = fo->curBlock;
bool newBl = (pos & 0x80) ? true : false;
if (newBl) {
bl = calcNewBlockPosition(fo->curBlock, fo->direction);
pos &= 3;
fo->u2 = 0;
}
if (updateObjectFlight(fo, bl, pos)) {
if (newBl)
runLevelScript(bl, 0x10);
if (updateFlyingObjectHitTest(fo, bl, pos))
endFlight = true;
} else {
if (fo->flags & 0x20) {
if (!updateFlyingObjectHitTest(fo, fo->curBlock, fo->curPos))
updateFlyingObject_s3(fo);
}
endFlight = true;
}
if (endFlight)
endObjectFlight(fo);
_sceneUpdateRequired = true;
}
}
void EobCoreEngine::timerProcessMonsters(int timerNum) {
updateMonsters(timerNum & 0x0f);
}
void EobCoreEngine::timerSpecialCharacterUpdate(int timerNum) {
int charIndex = timerNum & 0x0f;
EobCharacter *c = &_characters[charIndex];
uint32 ctime = _system->getMillis();
for (int i = 0; i < 10; i++) {
if (!c->timers[i])
continue;
if (c->timers[i] > ctime)
continue;
c->timers[i] = 0;
int evt = c->events[i];
if (evt < 0) {
removeCharacterEffect(evt, charIndex, 1);
continue;
}
switch (evt) {
case 2:
case 3:
setCharEventTimer(charIndex, (c->effectFlags & 0x10000) ? 9 : 36, evt + 2, 1);
case 0:
case 1:
case 4:
case 5:
setWeaponSlotStatus(charIndex, evt / 2, evt & 1);
break;
case 6:
c->damageTaken = 0;
gui_drawCharPortraitWithStats(charIndex);
break;
case 7:
_txt->printMessage(_characterStatusStrings7[0], -1, c->name);
c->strengthCur = c->strengthMax;
c->strengthExtCur = c->strengthExtMax;
if (_currentControlMode == 2)
gui_drawCharPortraitWithStats(charIndex);
break;
case 8:
if (c->flags & 2) {
calcAndInflictCharacterDamage(charIndex, 0, 0, 5, 0x400, 5, 3);
setCharEventTimer(charIndex, 546, 8, 1);
} else {
c->flags &= 0xfd;
gui_drawCharPortraitWithStats(charIndex);
}
break;
case 9:
if (c->flags & 4) {
_txt->printMessage(_characterStatusStrings9[0], -1, c->name);
c->flags &= 0xfb;
gui_drawCharPortraitWithStats(charIndex);
}
break;
case 11:
if (c->disabledSlots & 4) {
c->disabledSlots &= 0xfb;
if (_openBookChar == charIndex && _updateFlags)
gui_drawSpellbook();
}
break;
case 12:
c->effectFlags &= ~0x1000;
_txt->printMessage(_characterStatusStrings12[0], -1, c->name);
break;
default:
break;
}
}
uint32 nextTimer = (uint32)(-1);
for (int i = 0; i < 10; i++) {
if (c->timers[i] && c->timers[i] < nextTimer)
nextTimer = c->timers[i];
}
if (nextTimer == (uint32)(-1))
_timer->disable(timerNum);
else
_timer->setCountdown(timerNum, (nextTimer - ctime) / _tickLength);
}
void EobCoreEngine::timerUpdateTeleporters(int timerNum) {
_teleporterPulse ^= 1;
for (int i = 0; i < 18; i++) {
uint8 w = _visibleBlocks[i]->walls[_sceneDrawVarDown];
if (w == 44 || w == 74) {
_sceneUpdateRequired = true;
return;
}
}
}
void EobCoreEngine::timerUpdateFoodStatus(int timerNum) {
for (int i = 0; i < 6; i++) {
if (checkInventoryForRings(i, 2))
continue;
EobCharacter *c = &_characters[i];
if (c->food != 0 && c->flags & 1 && c->hitPointsCur > -10) {
c->food--;
gui_drawFoodStatusGraph(i);
}
}
}
void EobCoreEngine::timerUpdateMonsterIdleAnim(int timerNum) {
for (int i = 0; i < 18; i++) {
EobMonsterInPlay *m = &_monsters[i];
if (m->mode == 7 || m->mode == 10 || (m->flags & 0x20) || (rollDice(1, 2, 0) != 1))
continue;
m->idleAnimState = (rollDice(1, 2, 0) << 4) | rollDice(1, 2, 0);
checkSceneUpdateNeed(m->block);
}
}
} // End of namespace Kyra
#endif // ENABLE_EOB

View File

@ -47,58 +47,6 @@ void LoLEngine::setupTimers() {
_timer->addTimer(11, TimerV2(timerFadeMessageText), 360, false);
}
void LoLEngine::enableTimer(int id) {
_timer->enable(id);
_timer->setCountdown(id, _timer->getDelay(id));
}
void LoLEngine::enableSysTimer(int sysTimer) {
if (sysTimer != 2)
return;
for (int i = 0; i < _numClock2Timers; i++)
_timer->pauseSingleTimer(_clock2Timers[i], false);
}
void LoLEngine::disableSysTimer(int sysTimer) {
if (sysTimer != 2)
return;
for (int i = 0; i < _numClock2Timers; i++)
_timer->pauseSingleTimer(_clock2Timers[i], true);
}
void LoLEngine::timerProcessDoors(int timerNum) {
for (int i = 0; i < 3; i++) {
uint16 b = _openDoorState[i].block;
if (!b)
continue;
int v = _openDoorState[i].state;
int c = _openDoorState[i].wall;
_levelBlockProperties[b].walls[c] += v;
_levelBlockProperties[b].walls[c ^ 2] += v;
int snd = 31;
int flg = _wllWallFlags[_levelBlockProperties[b].walls[c]];
if (flg & 0x20)
snd = 33;
else if (v == -1)
snd = 32;
if (!(_updateFlags & 1)) {
snd_processEnvironmentalSoundEffect(snd, b);
if (!checkSceneUpdateNeed(b))
updateEnvironmentalSfx(0);
}
if (flg & 0x30)
_openDoorState[i].block = 0;
}
}
void LoLEngine::timerProcessMonsters(int timerNum) {
for (int i = timerNum & 0x0f; i < 30; i += 2)
updateMonster(&_monsters[i]);