KYRA: (EOB) - lots of fixes towards EOB1 playability

also implement some new code (EOB1 portals, burning hands spell, etc.)
This commit is contained in:
athrxx 2011-08-06 00:40:53 +02:00 committed by Johannes Schickel
parent aab9e62247
commit bac0caeb0f
26 changed files with 291 additions and 66 deletions

View file

@ -332,11 +332,13 @@ const ExtractFilename extractFilenames[] = {
{ kEobBaseDscDoorScaleMult5, kTypeRawData, false }, { kEobBaseDscDoorScaleMult5, kTypeRawData, false },
{ kEobBaseDscDoorScaleMult6, kTypeRawData, false }, { kEobBaseDscDoorScaleMult6, kTypeRawData, false },
{ kEobBaseDscDoorType5Offs, kTypeRawData, false }, { kEobBaseDscDoorType5Offs, kTypeRawData, false },
{ kEobBaseDscDoorXE, kTypeRawData, false },
{ kEobBaseDscDoorY1, kTypeRawData, false }, { kEobBaseDscDoorY1, kTypeRawData, false },
{ kEobBaseDscDoorY3, kTypeRawData, false }, { kEobBaseDscDoorY3, kTypeRawData, false },
{ kEobBaseDscDoorY4, kTypeRawData, false }, { kEobBaseDscDoorY4, kTypeRawData, false },
{ kEobBaseDscDoorY5, kTypeRawData, false }, { kEobBaseDscDoorY5, kTypeRawData, false },
{ kEobBaseDscDoorY6, kTypeRawData, false }, { kEobBaseDscDoorY6, kTypeRawData, false },
{ kEobBaseDscDoorY7, kTypeRawData, false },
{ kEobBaseDscDoorCoordsExt, kLolTypeRaw16, false }, { kEobBaseDscDoorCoordsExt, kLolTypeRaw16, false },
{ kEobBaseDscItemPosIndex, kTypeRawData, false }, { kEobBaseDscItemPosIndex, kTypeRawData, false },
@ -401,6 +403,7 @@ const ExtractFilename extractFilenames[] = {
{ kEobBaseSpellProperties, kTypeRawData, false }, { kEobBaseSpellProperties, kTypeRawData, false },
{ kEobBaseMagicFlightProps, kTypeRawData, false }, { kEobBaseMagicFlightProps, kTypeRawData, false },
{ kEobBaseTurnUndeadEffect, kTypeRawData, false }, { kEobBaseTurnUndeadEffect, kTypeRawData, false },
{ kEobBaseBurningHandsDest, kTypeRawData, false },
// EYE OF THE BEHOLDER I // EYE OF THE BEHOLDER I
{ kEob1MainMenuStrings, kTypeStringList, true }, { kEob1MainMenuStrings, kTypeStringList, true },
@ -1516,6 +1519,8 @@ const char *getIdString(const int id) {
return "kEobBaseDscDoorScaleMult6"; return "kEobBaseDscDoorScaleMult6";
case kEobBaseDscDoorType5Offs: case kEobBaseDscDoorType5Offs:
return "kEobBaseDscDoorType5Offs"; return "kEobBaseDscDoorType5Offs";
case kEobBaseDscDoorXE:
return "kEobBaseDscDoorXE";
case kEobBaseDscDoorY1: case kEobBaseDscDoorY1:
return "kEobBaseDscDoorY1"; return "kEobBaseDscDoorY1";
case kEobBaseDscDoorY3: case kEobBaseDscDoorY3:
@ -1526,6 +1531,8 @@ const char *getIdString(const int id) {
return "kEobBaseDscDoorY5"; return "kEobBaseDscDoorY5";
case kEobBaseDscDoorY6: case kEobBaseDscDoorY6:
return "kEobBaseDscDoorY6"; return "kEobBaseDscDoorY6";
case kEobBaseDscDoorY7:
return "kEobBaseDscDoorY7";
case kEobBaseDscDoorCoordsExt: case kEobBaseDscDoorCoordsExt:
return "kEobBaseDscDoorCoordsExt"; return "kEobBaseDscDoorCoordsExt";
case kEobBaseDscItemPosIndex: case kEobBaseDscItemPosIndex:
@ -1635,6 +1642,8 @@ const char *getIdString(const int id) {
return "kEobBaseMagicFlightProps"; return "kEobBaseMagicFlightProps";
case kEobBaseTurnUndeadEffect: case kEobBaseTurnUndeadEffect:
return "kEobBaseTurnUndeadEffect"; return "kEobBaseTurnUndeadEffect";
case kEobBaseBurningHandsDest:
return "kEobBaseBurningHandsDest";
case kEob1MainMenuStrings: case kEob1MainMenuStrings:
return "kEob1MainMenuStrings"; return "kEob1MainMenuStrings";
case kEob1DoorShapeDefs: case kEob1DoorShapeDefs:

View file

@ -332,11 +332,13 @@ enum kExtractID {
kEobBaseDscDoorScaleMult5, kEobBaseDscDoorScaleMult5,
kEobBaseDscDoorScaleMult6, kEobBaseDscDoorScaleMult6,
kEobBaseDscDoorType5Offs, kEobBaseDscDoorType5Offs,
kEobBaseDscDoorXE,
kEobBaseDscDoorY1, kEobBaseDscDoorY1,
kEobBaseDscDoorY3, kEobBaseDscDoorY3,
kEobBaseDscDoorY4, kEobBaseDscDoorY4,
kEobBaseDscDoorY5, kEobBaseDscDoorY5,
kEobBaseDscDoorY6, kEobBaseDscDoorY6,
kEobBaseDscDoorY7,
kEobBaseDscDoorCoordsExt, kEobBaseDscDoorCoordsExt,
kEobBaseDscItemPosIndex, kEobBaseDscItemPosIndex,
@ -402,6 +404,7 @@ enum kExtractID {
kEobBaseSpellProperties, kEobBaseSpellProperties,
kEobBaseMagicFlightProps, kEobBaseMagicFlightProps,
kEobBaseTurnUndeadEffect, kEobBaseTurnUndeadEffect,
kEobBaseBurningHandsDest,
kEob1MainMenuStrings, kEob1MainMenuStrings,
kEob1DoorShapeDefs, kEob1DoorShapeDefs,

View file

@ -1189,6 +1189,7 @@ const int eob1FloppyNeed[] = {
kEobBaseSpellProperties, kEobBaseSpellProperties,
kEobBaseMagicFlightProps, kEobBaseMagicFlightProps,
kEobBaseTurnUndeadEffect, kEobBaseTurnUndeadEffect,
kEobBaseBurningHandsDest,
kLolEobCommonDscDoorShapeIndex, kLolEobCommonDscDoorShapeIndex,
kEobBaseWllFlagPreset, kEobBaseWllFlagPreset,
@ -1200,12 +1201,13 @@ const int eob1FloppyNeed[] = {
kEobBaseDscDoorScaleMult4, kEobBaseDscDoorScaleMult4,
kEobBaseDscDoorScaleMult5, kEobBaseDscDoorScaleMult5,
kEobBaseDscDoorScaleMult6, kEobBaseDscDoorScaleMult6,
kEobBaseDscDoorXE,
kEobBaseDscDoorY1, kEobBaseDscDoorY1,
kLolEobCommonDscDoorY2,
kEobBaseDscDoorY3, kEobBaseDscDoorY3,
kEobBaseDscDoorY4, kEobBaseDscDoorY4,
kEobBaseDscDoorY5, kEobBaseDscDoorY5,
kEobBaseDscDoorY6, kEobBaseDscDoorY6,
kEobBaseDscDoorY7,
kEobBaseDscDoorCoordsExt, kEobBaseDscDoorCoordsExt,
kEobBaseDscItemPosIndex, kEobBaseDscItemPosIndex,
@ -1408,6 +1410,7 @@ const int eob2FloppyNeed[] = {
kEobBaseSpellProperties, kEobBaseSpellProperties,
kEobBaseMagicFlightProps, kEobBaseMagicFlightProps,
kEobBaseTurnUndeadEffect, kEobBaseTurnUndeadEffect,
kEobBaseBurningHandsDest,
kLolEobCommonDscDoorShapeIndex, kLolEobCommonDscDoorShapeIndex,
kEobBaseWllFlagPreset, kEobBaseWllFlagPreset,

View file

@ -2001,6 +2001,11 @@ const ExtractEntrySearchData kEobBaseDscDoorType5OffsProvider[] = {
EXTRACT_END_ENTRY EXTRACT_END_ENTRY
}; };
const ExtractEntrySearchData kEobBaseDscDoorXEProvider[] = {
{ UNK_LANG, kPlatformPC, { 0x00000020, 0x0000010F, { { 0x7B, 0x7D, 0x03, 0xDE, 0x33, 0x95, 0xB8, 0xFD, 0xAD, 0x72, 0x44, 0x7D, 0x47, 0xFE, 0x04, 0x3D } } } },
EXTRACT_END_ENTRY
};
const ExtractEntrySearchData kEobBaseDscDoorY1Provider[] = { const ExtractEntrySearchData kEobBaseDscDoorY1Provider[] = {
{ UNK_LANG, kPlatformPC, { 0x00000004, 0x000000D7, { { 0x25, 0xAE, 0xF4, 0x99, 0xE8, 0x97, 0x47, 0xAE, 0x75, 0xF3, 0xA9, 0x70, 0x4C, 0x70, 0xF3, 0x11 } } } }, // EOB 1 { UNK_LANG, kPlatformPC, { 0x00000004, 0x000000D7, { { 0x25, 0xAE, 0xF4, 0x99, 0xE8, 0x97, 0x47, 0xAE, 0x75, 0xF3, 0xA9, 0x70, 0x4C, 0x70, 0xF3, 0x11 } } } }, // EOB 1
{ UNK_LANG, kPlatformPC, { 0x00000004, 0x000000D8, { { 0xB4, 0xAA, 0x0D, 0x91, 0x58, 0x22, 0x16, 0xCF, 0xC5, 0x9D, 0x8D, 0xA1, 0xB4, 0x40, 0x83, 0x0E } } } }, // EOB 2 { UNK_LANG, kPlatformPC, { 0x00000004, 0x000000D8, { { 0xB4, 0xAA, 0x0D, 0x91, 0x58, 0x22, 0x16, 0xCF, 0xC5, 0x9D, 0x8D, 0xA1, 0xB4, 0x40, 0x83, 0x0E } } } }, // EOB 2
@ -2027,6 +2032,11 @@ const ExtractEntrySearchData kEobBaseDscDoorY6Provider[] = {
EXTRACT_END_ENTRY EXTRACT_END_ENTRY
}; };
const ExtractEntrySearchData kEobBaseDscDoorY7Provider[] = {
{ UNK_LANG, kPlatformPC, { 0x00000004, 0x000000DA, { { 0xA9, 0x24, 0x71, 0x8A, 0x18, 0x24, 0x6D, 0x0A, 0x65, 0x12, 0xBB, 0x1F, 0xE7, 0x95, 0xC5, 0xA4 } } } },
EXTRACT_END_ENTRY
};
const ExtractEntrySearchData kEobBaseDscDoorCoordsExtProvider[] = { const ExtractEntrySearchData kEobBaseDscDoorCoordsExtProvider[] = {
{ UNK_LANG, kPlatformPC, { 0x00000048, 0x00000C8E, { { 0x2E, 0x0E, 0xB2, 0xAC, 0xE7, 0x0F, 0xDF, 0x38, 0xDF, 0x92, 0xB7, 0xB5, 0xA2, 0xFD, 0x40, 0x2D } } } }, { UNK_LANG, kPlatformPC, { 0x00000048, 0x00000C8E, { { 0x2E, 0x0E, 0xB2, 0xAC, 0xE7, 0x0F, 0xDF, 0x38, 0xDF, 0x92, 0xB7, 0xB5, 0xA2, 0xFD, 0x40, 0x2D } } } },
EXTRACT_END_ENTRY EXTRACT_END_ENTRY
@ -2340,7 +2350,14 @@ const ExtractEntrySearchData kEobBaseMagicFlightPropsProvider[] = {
}; };
const ExtractEntrySearchData kEobBaseTurnUndeadEffectProvider[] = { const ExtractEntrySearchData kEobBaseTurnUndeadEffectProvider[] = {
{ UNK_LANG, kPlatformUnknown, { 0x0000008C, 0x00002E8B, { { 0x96, 0x15, 0x61, 0x12, 0x43, 0xCF, 0x3A, 0x84, 0x1A, 0x89, 0xB5, 0x32, 0x0D, 0xB3, 0x20, 0x67 } } } }, { UNK_LANG, kPlatformPC, { 0x0000008C, 0x00002E8B, { { 0x96, 0x15, 0x61, 0x12, 0x43, 0xCF, 0x3A, 0x84, 0x1A, 0x89, 0xB5, 0x32, 0x0D, 0xB3, 0x20, 0x67 } } } },
EXTRACT_END_ENTRY
};
const ExtractEntrySearchData kEobBaseBurningHandsDestProvider[] = {
{ UNK_LANG, kPlatformPC, { 0x00000008, 0x0000000C, { { 0x61, 0xD7, 0xAB, 0xE1, 0x56, 0x54, 0x51, 0x5B, 0xD9, 0x59, 0x2D, 0x3D, 0xAE, 0xA4, 0x49, 0x31 } } } }, // EOB1
{ UNK_LANG, kPlatformPC, { 0x00000020, 0x0000003E, { { 0xA5, 0x8C, 0xCA, 0x13, 0xED, 0x0F, 0xB7, 0xA2, 0xD7, 0x9C, 0xCD, 0x11, 0x65, 0x11, 0x4B, 0xD8 } } } }, // EOB2
EXTRACT_END_ENTRY EXTRACT_END_ENTRY
}; };
@ -3775,11 +3792,13 @@ const ExtractEntry extractProviders[] = {
{ kEobBaseDscDoorScaleMult5, kEobBaseDscDoorScaleMult5Provider }, { kEobBaseDscDoorScaleMult5, kEobBaseDscDoorScaleMult5Provider },
{ kEobBaseDscDoorScaleMult6, kEobBaseDscDoorScaleMult6Provider }, { kEobBaseDscDoorScaleMult6, kEobBaseDscDoorScaleMult6Provider },
{ kEobBaseDscDoorType5Offs, kEobBaseDscDoorType5OffsProvider }, { kEobBaseDscDoorType5Offs, kEobBaseDscDoorType5OffsProvider },
{ kEobBaseDscDoorXE, kEobBaseDscDoorXEProvider },
{ kEobBaseDscDoorY1, kEobBaseDscDoorY1Provider }, { kEobBaseDscDoorY1, kEobBaseDscDoorY1Provider },
{ kEobBaseDscDoorY3, kEobBaseDscDoorY3Provider }, { kEobBaseDscDoorY3, kEobBaseDscDoorY3Provider },
{ kEobBaseDscDoorY4, kEobBaseDscDoorY4Provider }, { kEobBaseDscDoorY4, kEobBaseDscDoorY4Provider },
{ kEobBaseDscDoorY5, kEobBaseDscDoorY5Provider }, { kEobBaseDscDoorY5, kEobBaseDscDoorY5Provider },
{ kEobBaseDscDoorY6, kEobBaseDscDoorY6Provider }, { kEobBaseDscDoorY6, kEobBaseDscDoorY6Provider },
{ kEobBaseDscDoorY7, kEobBaseDscDoorY7Provider },
{ kEobBaseDscDoorCoordsExt, kEobBaseDscDoorCoordsExtProvider }, { kEobBaseDscDoorCoordsExt, kEobBaseDscDoorCoordsExtProvider },
{ kEobBaseDscItemPosIndex, kEobBaseDscItemPosIndexProvider }, { kEobBaseDscItemPosIndex, kEobBaseDscItemPosIndexProvider },
{ kEobBaseDscItemShpX, kEobBaseDscItemShpXProvider }, { kEobBaseDscItemShpX, kEobBaseDscItemShpXProvider },
@ -3843,6 +3862,7 @@ const ExtractEntry extractProviders[] = {
{ kEobBaseSpellProperties, kEobBaseSpellPropertiesProvider }, { kEobBaseSpellProperties, kEobBaseSpellPropertiesProvider },
{ kEobBaseMagicFlightProps, kEobBaseMagicFlightPropsProvider }, { kEobBaseMagicFlightProps, kEobBaseMagicFlightPropsProvider },
{ kEobBaseTurnUndeadEffect, kEobBaseTurnUndeadEffectProvider }, { kEobBaseTurnUndeadEffect, kEobBaseTurnUndeadEffectProvider },
{ kEobBaseBurningHandsDest, kEobBaseBurningHandsDestProvider },
{ kEob1MainMenuStrings, kEob1MainMenuStringsProvider }, { kEob1MainMenuStrings, kEob1MainMenuStringsProvider },
{ kEob1DoorShapeDefs, kEob1DoorShapeDefsProvider }, { kEob1DoorShapeDefs, kEob1DoorShapeDefsProvider },

Binary file not shown.

View file

@ -236,7 +236,7 @@ bool CharacterGenerator::start(EobCharacter *characters, uint8 ***faceShapes) {
} }
void CharacterGenerator::init() { void CharacterGenerator::init() {
_screen->loadEobBitmap("CHARGENA", 3, 3); _screen->loadShapeSetBitmap("CHARGENA", 3, 3);
if (_faceShapes) { if (_faceShapes) {
for (int i = 0; i < 44; i++) for (int i = 0; i < 44; i++)
delete[] _faceShapes[i]; delete[] _faceShapes[i];
@ -248,8 +248,8 @@ void CharacterGenerator::init() {
_faceShapes[i] = _screen->encodeShape((i % 10) << 2, (i / 10) << 5, 4, 32, true); _faceShapes[i] = _screen->encodeShape((i % 10) << 2, (i / 10) << 5, 4, 32, true);
_screen->_curPage = 0; _screen->_curPage = 0;
_screen->loadEobCpsFileToPage("CHARGEN", 0, 3, 3, 0); _screen->loadEobBitmap("CHARGEN", 0, 3, 3, 0);
_screen->loadEobBitmap("CHARGENB", 3, 3); _screen->loadShapeSetBitmap("CHARGENB", 3, 3);
if (_chargenMagicShapes) { if (_chargenMagicShapes) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
delete[] _chargenMagicShapes[i]; delete[] _chargenMagicShapes[i];

View file

@ -78,6 +78,9 @@ Common::Error EobEngine::init() {
_scriptTimersCount = 1; _scriptTimersCount = 1;
//_wllWallFlags[132] = 0x1f;
_wllWallFlags[133] = 1;
return Common::kNoError; return Common::kNoError;
} }
@ -341,8 +344,25 @@ void EobEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int typ
} }
} }
void EobEngine::updateScriptTimersExtra() {
int cnt = 0;
for (int i = 1; i < 30; i++) {
if (_monsters[i].hitPointsCur <= 0)
cnt++;
}
if (!cnt) {
for (int i = 1; i < 30; i++) {
if (getBlockDistance(_monsters[i].block, _currentBlock) > 3) {
killMonster(&_monsters[i], true);
break;
}
}
}
}
void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) { void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {
_screen->loadEobBitmap("DOOR", 5, 3); _screen->loadShapeSetBitmap("DOOR", 5, 3);
_screen->_curPage = 2; _screen->_curPage = 2;
if (doorType1 != 0xff) { if (doorType1 != 0xff) {
@ -351,8 +371,8 @@ void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s
_doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); _doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
enc = &_doorSwitchShapeEncodeDefs[(doorType1 * 3 + i) << 2]; enc = &_doorSwitchShapeEncodeDefs[(doorType1 * 3 + i) << 2];
_doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); _doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
_doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 << 1]; _doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 * 6 + i * 2];
_doorSwitches[shapeId1 + i].y = _doorSwitchCoords[(doorType1 << 1) + 1]; _doorSwitches[shapeId1 + i].y = _doorSwitchCoords[doorType1 * 6 + i * 2 + 1];
} }
} }
@ -362,8 +382,8 @@ void EobEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s
_doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); _doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
enc = &_doorSwitchShapeEncodeDefs[(doorType2 * 3 + i) << 2]; enc = &_doorSwitchShapeEncodeDefs[(doorType2 * 3 + i) << 2];
_doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]); _doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3]);
_doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 << 1]; _doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 * 6 + i * 2];
_doorSwitches[shapeId2 + i].y = _doorSwitchCoords[(doorType2 << 1) + 1]; _doorSwitches[shapeId2 + i].y = _doorSwitchCoords[doorType2 * 6 + i * 2+ 1];
} }
} }
@ -383,7 +403,7 @@ void EobEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wal
case 4: case 4:
case 5: case 5:
case 6: case 6:
y = _dscDoorY2[mDim] - shp[1]; y = _dscDoorY6[mDim] - shp[1];
d1 = _dscDoorCoordsExt[index << 1] >> 3; d1 = _dscDoorCoordsExt[index << 1] >> 3;
d2 = _dscDoorCoordsExt[(index << 1) + 1] >> 3; d2 = _dscDoorCoordsExt[(index << 1) + 1] >> 3;
if (_shpDmX1 > d1) if (_shpDmX1 > d1)
@ -403,7 +423,7 @@ void EobEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wal
case 7: case 7:
case 8: case 8:
case 9: case 9:
y = _dscDoorY3[mDim] - _doorShapes[shapeIndex + 3][1]; y = _dscDoorY7[mDim] - _doorShapes[shapeIndex + 3][1];
d1 = x - (_doorShapes[shapeIndex + 3][2] << 2); d1 = x - (_doorShapes[shapeIndex + 3][2] << 2);
x -= (shp[2] << 2); x -= (shp[2] << 2);
drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], d1, y, 5); drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], d1, y, 5);

View file

@ -81,6 +81,7 @@ private:
// Monsters // Monsters
void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem); void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
void updateScriptTimersExtra();
// Level // Level
void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2); void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2);
@ -94,6 +95,7 @@ private:
const uint8 *_dscDoorY4; const uint8 *_dscDoorY4;
const uint8 *_dscDoorY5; const uint8 *_dscDoorY5;
const uint8 *_dscDoorY6; const uint8 *_dscDoorY6;
const uint8 *_dscDoorY7;
const uint8 *_doorShapeEncodeDefs; const uint8 *_doorShapeEncodeDefs;
const uint8 *_doorSwitchShapeEncodeDefs; const uint8 *_doorSwitchShapeEncodeDefs;

View file

@ -159,7 +159,7 @@ void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) {
void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) { void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) {
int cp = _screen->setCurPage(2); int cp = _screen->setCurPage(2);
_screen->loadEobBitmap(file, 3, 3); _screen->loadShapeSetBitmap(file, 3, 3);
uint8 tmpPal[16]; uint8 tmpPal[16];
uint8 newPal[16]; uint8 newPal[16];
@ -291,7 +291,7 @@ bool DarkMoonEngine::killMonsterExtra(EobMonsterInPlay *m) {
} }
const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) { const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) {
_screen->loadEobBitmap(filename, 3, 3); _screen->loadShapeSetBitmap(filename, 3, 3);
for (int i = 0; i < 3; i++) { 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)); _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; shapeDefs += 8;

View file

@ -98,6 +98,7 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa
_dscDoorScaleMult2 = 0; _dscDoorScaleMult2 = 0;
_dscDoorScaleMult3 = 0; _dscDoorScaleMult3 = 0;
_dscDoorY1 = 0; _dscDoorY1 = 0;
_dscDoorXE = 0;
_color9 = 17; _color9 = 17;
_color10 = 23; _color10 = 23;
@ -137,6 +138,7 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa
_spellAnimBuffer = 0; _spellAnimBuffer = 0;
_clericSpellOffset = 0; _clericSpellOffset = 0;
_restPartyElapsedTime = 0; _restPartyElapsedTime = 0;
_allowSkip = false;
_rrCount = 0; _rrCount = 0;
memset(_rrNames, 0, 10 * sizeof(const char*)); memset(_rrNames, 0, 10 * sizeof(const char*));
@ -980,7 +982,7 @@ void EobCoreEngine::neutralizePoison(int character) {
} }
void EobCoreEngine::npcSequence(int npcIndex) { void EobCoreEngine::npcSequence(int npcIndex) {
_screen->loadEobBitmap("OUTTAKE", 5, 3); _screen->loadShapeSetBitmap("OUTTAKE", 5, 3);
_screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK); _screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 6, Screen::CR_NO_P_CHECK);
drawNpcScene(npcIndex); drawNpcScene(npcIndex);
@ -1019,7 +1021,7 @@ void EobCoreEngine::initNpc(int npcIndex) {
c->inventory[i] = duplicateItem(c->inventory[i]); c->inventory[i] = duplicateItem(c->inventory[i]);
} }
_screen->loadEobBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3); _screen->loadShapeSetBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3);
_screen->_curPage = 2; _screen->_curPage = 2;
c->faceShape = _screen->encodeShape(npcIndex << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true); c->faceShape = _screen->encodeShape(npcIndex << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true);
_screen->_curPage = 0; _screen->_curPage = 0;
@ -1257,7 +1259,7 @@ void EobCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i
if (scumm_stricmp(_dialogueLastBitmap, file)) { if (scumm_stricmp(_dialogueLastBitmap, file)) {
if (!destRect) { if (!destRect) {
if (!(flags & 1)) { if (!(flags & 1)) {
_screen->loadEobCpsFileToPage("BORDER", 0, 3, 3, 2); _screen->loadEobBitmap("BORDER", 0, 3, 3, 2);
_screen->copyRegion(0, 0, 0, 0, 184, 121, 2, page, Screen::CR_NO_P_CHECK); _screen->copyRegion(0, 0, 0, 0, 184, 121, 2, page, Screen::CR_NO_P_CHECK);
} else { } else {
_screen->copyRegion(0, 0, 0, 0, 184, 121, 0, page, Screen::CR_NO_P_CHECK); _screen->copyRegion(0, 0, 0, 0, 184, 121, 0, page, Screen::CR_NO_P_CHECK);
@ -1267,7 +1269,7 @@ void EobCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i
_screen->copyRegion(0, 0, 0, 0, 184, 121, 2, 6, Screen::CR_NO_P_CHECK); _screen->copyRegion(0, 0, 0, 0, 184, 121, 2, 6, Screen::CR_NO_P_CHECK);
} }
_screen->loadEobCpsFileToPage(file, 0, 3, 3, 2); _screen->loadEobBitmap(file, 0, 3, 3, 2);
strcpy(_dialogueLastBitmap, file); strcpy(_dialogueLastBitmap, file);
} }
@ -1407,16 +1409,12 @@ bool EobCoreEngine::restParty_checkSpellsToLearn() {
return false; return false;
} }
void EobCoreEngine::restParty_npc() {
}
bool EobCoreEngine::restParty_extraAbortCondition() { bool EobCoreEngine::restParty_extraAbortCondition() {
return false; return false;
} }
void EobCoreEngine::delay(uint32 millis, bool, bool) { void EobCoreEngine::delay(uint32 millis, bool, bool) {
while (millis && !shouldQuit() && !skipFlag()) { while (millis && !shouldQuit() && !(_allowSkip && skipFlag())) {
updateInput(); updateInput();
uint32 step = MIN<uint32>(millis, (_tickLength / 5)); uint32 step = MIN<uint32>(millis, (_tickLength / 5));
_system->delayMillis(step); _system->delayMillis(step);
@ -1501,7 +1499,75 @@ int EobCoreEngine::countResurrectionCandidates() {
} }
void EobCoreEngine::seq_portal() { void EobCoreEngine::seq_portal() {
//_portalSeq releaseDoorShapes();
releaseMonsterShapes(0, 36);
releaseDecorations();
uint8 *shapes1[5];
uint8 *shapes2[5];
uint8 *shapes3[5];
uint8 *shape0;
_screen->loadShapeSetBitmap("PORTALA", 5, 3);
for (int i = 0; i < 5; i++) {
shapes1[i] = _screen->encodeShape(i * 3, 0, 3, 75);
shapes2[i] = _screen->encodeShape(i * 3, 80, 3, 75);
shapes3[i] = _screen->encodeShape(15, i * 18, 15, 18);
}
shape0 = _screen->encodeShape(30, 0, 8, 77);
_screen->loadEobBitmap("PORTALB", 0, 5, 3, 2);
snd_playSoundEffect(33);
snd_playSoundEffect(19);
_screen->copyRegion(24, 0, 24, 0, 144, 104, 2, 5, Screen::CR_NO_P_CHECK);
_screen->copyRegion(24, 0, 24, 0, 144, 104, 0, 2, Screen::CR_NO_P_CHECK);
_screen->drawShape(2, shapes3[0], 28, 9, 0);
_screen->drawShape(2, shapes1[0], 34, 28, 0);
_screen->drawShape(2, shapes2[0], 120, 28, 0);
_screen->drawShape(2, shape0, 56, 27, 0);
_screen->crossFadeRegion(24, 0, 24, 0, 144, 104, 2, 0);
_screen->copyRegion(24, 0, 24, 0, 144, 104, 5, 2, Screen::CR_NO_P_CHECK);
delay(30 * _tickLength);
for (const int8 *pos = _portalSeq; *pos > -1 && !shouldQuit(); ) {
int s = *pos++;
_screen->drawShape(0, shapes3[s], 28, 9, 0);
_screen->drawShape(0, shapes1[s], 34, 28, 0);
_screen->drawShape(0, shapes2[s], 120, 28, 0);
if ((s == 1) && (pos >= _portalSeq + 3)) {
if (*(pos - 3) == 0) {
snd_playSoundEffect(24);
snd_playSoundEffect(86);
}
}
s = *pos++;
if (s == 0) {
_screen->drawShape(0, shape0, 56, 27, 0);
} else {
s--;
_screen->copyRegion((s % 5) << 6, s / 5 * 77, 56, 27, 64, 77, 2, 0, Screen::CR_NO_P_CHECK);
if (s == 0)
snd_playSoundEffect(31);
else if (s == 3) {
if (*(pos - 2) == 3)
snd_playSoundEffect(90);
}
}
_screen->updateScreen();
delay(2 * _tickLength);
}
delete[] shape0;
for (int i = 0; i < 5; i++) {
delete[] shapes1[i];
delete[] shapes2[i];
delete[] shapes3[i];
}
} }
bool EobCoreEngine::checkPassword() { bool EobCoreEngine::checkPassword() {
@ -1830,10 +1896,13 @@ bool EobCoreEngine::monsterAttackHitTest(EobMonsterInPlay *m, int charIndex) {
int r = rollDice(1, 20); int r = rollDice(1, 20);
if (r != 20) { if (r != 20) {
// Prot from evil
if (_characters[charIndex].effectFlags & 0x800) if (_characters[charIndex].effectFlags & 0x800)
r -= 2; r -= 2;
// blur
if (_characters[charIndex].effectFlags & 0x10) if (_characters[charIndex].effectFlags & 0x10)
r -= 2; r -= 2;
// prayer
if (_partyEffectFlags & 0x8000) if (_partyEffectFlags & 0x8000)
r--; r--;
} }

View file

@ -508,6 +508,7 @@ protected:
void updateMonsters(int unit); void updateMonsters(int unit);
void updateMonsterDest(EobMonsterInPlay *m); void updateMonsterDest(EobMonsterInPlay *m);
void updateMonsterDest2(EobMonsterInPlay *m); void updateMonsterDest2(EobMonsterInPlay *m);
void updateAllMonsterDests();
void turnFriendlyMonstersHostile(); void turnFriendlyMonstersHostile();
int getNextMonsterDirection(int curBlock, int destBlock); int getNextMonsterDirection(int curBlock, int destBlock);
int getNextMonsterPos(EobMonsterInPlay *m, int block); int getNextMonsterPos(EobMonsterInPlay *m, int block);
@ -619,11 +620,12 @@ protected:
const uint8 *_dscDoorScaleMult2; const uint8 *_dscDoorScaleMult2;
const uint8 *_dscDoorScaleMult3; const uint8 *_dscDoorScaleMult3;
const uint8 *_dscDoorY1; const uint8 *_dscDoorY1;
const uint8 *_dscDoorXE;
const uint8 *_wllFlagPreset; const uint8 *_wllFlagPreset;
int _wllFlagPresetSize; int _wllFlagPresetSize;
const uint8 *_teleporterShapeCoords; const uint8 *_teleporterShapeCoords;
const uint8 *_portalSeq; const int8 *_portalSeq;
// Script // Script
void runLevelScript(int block, int flags); void runLevelScript(int block, int flags);
@ -633,6 +635,7 @@ protected:
const uint8 *initScriptTimers(const uint8 *pos); const uint8 *initScriptTimers(const uint8 *pos);
void updateScriptTimers(); void updateScriptTimers();
virtual void updateScriptTimersExtra() {}
EobInfProcessor *_inf; EobInfProcessor *_inf;
int _stepCounter; int _stepCounter;
@ -803,7 +806,7 @@ protected:
int restParty_getCharacterWithLowestHp(); int restParty_getCharacterWithLowestHp();
bool restParty_checkHealSpells(int charIndex); bool restParty_checkHealSpells(int charIndex);
bool restParty_checkSpellsToLearn(); bool restParty_checkSpellsToLearn();
virtual void restParty_npc(); virtual void restParty_npc() {}
virtual bool restParty_extraAbortCondition(); virtual bool restParty_extraAbortCondition();
// misc // misc
@ -840,6 +843,8 @@ protected:
const char *_rrNames[10]; const char *_rrNames[10];
int8 _rrId[10]; int8 _rrId[10];
bool _allowSkip;
Screen_Eob *_screen; Screen_Eob *_screen;
GUI_Eob *_gui; GUI_Eob *_gui;
@ -881,6 +886,7 @@ protected:
int _dstMonsterIndex; int _dstMonsterIndex;
bool _preventMonsterFlash; bool _preventMonsterFlash;
int16 _foundMonstersArray[5]; int16 _foundMonstersArray[5];
int8 _monsterBlockPosArray[6];
// magic // magic
void useMagicBookOrSymbol(int charIndex, int type); void useMagicBookOrSymbol(int charIndex, int type);
@ -969,6 +975,7 @@ protected:
void spellCallback_start_heal(); void spellCallback_start_heal();
void spellCallback_start_layOnHands(); void spellCallback_start_layOnHands();
void spellCallback_start_turnUndead(); void spellCallback_start_turnUndead();
bool spellCallback_end_kuotoaAttack(EobFlyingObject *fo);
bool spellCallback_end_unk1Passive(EobFlyingObject *fo); bool spellCallback_end_unk1Passive(EobFlyingObject *fo);
bool spellCallback_end_unk2Passive(EobFlyingObject *fo); bool spellCallback_end_unk2Passive(EobFlyingObject *fo);
bool spellCallback_end_deathSpellPassive(EobFlyingObject *fo); bool spellCallback_end_deathSpellPassive(EobFlyingObject *fo);
@ -1038,6 +1045,7 @@ protected:
const uint8 *_magicFlightObjectProperties; const uint8 *_magicFlightObjectProperties;
const uint8 *_turnUndeadEffect; const uint8 *_turnUndeadEffect;
const uint8 *_burningHandsDest;
// Menu // Menu
EobMenuDef *_menuDefs; EobMenuDef *_menuDefs;

View file

@ -150,7 +150,7 @@ Button *EobCoreEngine::gui_getButton(Button *buttonList, int index) {
} }
void EobCoreEngine::gui_drawPlayField(bool refresh) { void EobCoreEngine::gui_drawPlayField(bool refresh) {
_screen->loadEobCpsFileToPage("PLAYFLD", 0, 5, 3, 2); _screen->loadEobBitmap("PLAYFLD", 0, 5, 3, 2);
int cp = _screen->setCurPage(2); int cp = _screen->setCurPage(2);
gui_drawCompass(true); gui_drawCompass(true);
@ -163,7 +163,7 @@ void EobCoreEngine::gui_drawPlayField(bool refresh) {
if (!_loading) if (!_loading)
_screen->updateScreen(); _screen->updateScreen();
_screen->loadEobCpsFileToPage("INVENT", 0, 5, 3, 2); _screen->loadEobBitmap("INVENT", 0, 5, 3, 2);
} }
void EobCoreEngine::gui_restorePlayField() { void EobCoreEngine::gui_restorePlayField() {

View file

@ -142,7 +142,7 @@ void EobCoreEngine::usePotion(int charIndex, int weaponSlot) {
} }
void EobCoreEngine::useWand(int charIndex, int weaponSlot) { void EobCoreEngine::useWand(int charIndex, int weaponSlot) {
int v = _items[_characters[charIndex].inventory[weaponSlot]].value - 1; int v = _items[_characters[charIndex].inventory[weaponSlot]].value;
if (!v) { if (!v) {
_txt->printMessage(_wandStrings[0]); _txt->printMessage(_wandStrings[0]);
return; return;
@ -535,7 +535,7 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d
if (!fo->item && (_characters[c].effectFlags & 8)) { if (!fo->item && (_characters[c].effectFlags & 8)) {
res = true; res = true;
} else { } else {
if ((_characters[c].flags & 1) && hitTest && !monsterAttackHitTest(&_monsters[0], c)) { if ((_characters[c].flags & 1) && (!hitTest || monsterAttackHitTest(&_monsters[0], c))) {
int dmg = rollDice(dcTimes, dcPips, dcOffs) * level; int dmg = rollDice(dcTimes, dcPips, dcOffs) * level;
res = true; res = true;
calcAndInflictCharacterDamage(c, 0, 0, dmg, dmgFlag, s, dmgType); calcAndInflictCharacterDamage(c, 0, 0, dmg, dmgFlag, s, dmgType);
@ -638,7 +638,31 @@ void EobCoreEngine::spellCallback_start_armor() {
} }
void EobCoreEngine::spellCallback_start_burningHands() { void EobCoreEngine::spellCallback_start_burningHands() {
static const int16 bX[] = { 0, 152, 24, 120, 56, 88 };
static const int8 bY[] = { 64, 64, 56, 56, 56, 56 };
for (int i = 0; i < 6; i++)
drawBlockObject(i & 1, 0, _firebeamShapes[(5 - i) >> 1], bX[i], bY[i], 0);
_screen->updateScreen();
delay(2 * _tickLength);
int cl = getCharacterMageLevel(_openBookChar);
int bl = calcNewBlockPosition(_currentBlock, _currentDirection);
const int8 *pos = getMonsterBlockPositions(bl);
_preventMonsterFlash = true;
int numDest = (_flags.gameID == GI_EOB1) ? 2 : 6;
const uint8 *d = &_burningHandsDest[_currentDirection * (_flags.gameID == GI_EOB1 ? 2 : 8)];
for (int i = 0; i < numDest; i++, d++) {
if (pos[*d] == -1)
continue;
calcAndInflictMonsterDamage(&_monsters[pos[*d]], 1, 3, cl << 1, 0x21, 4, 0);
}
updateAllMonsterShapes();
_sceneUpdateRequired = true;
} }
void EobCoreEngine::spellCallback_start_detectMagic() { void EobCoreEngine::spellCallback_start_detectMagic() {
@ -949,6 +973,10 @@ void EobCoreEngine::spellCallback_start_turnUndead() {
_preventMonsterFlash = false; _preventMonsterFlash = false;
} }
bool EobCoreEngine::spellCallback_end_kuotoaAttack(EobFlyingObject *fo) {
return magicObjectDamageHit(fo, 0, 0, 12, 1);
}
bool EobCoreEngine::spellCallback_end_unk1Passive(EobFlyingObject *fo) { bool EobCoreEngine::spellCallback_end_unk1Passive(EobFlyingObject *fo) {
bool res = false; bool res = false;
if (_partyEffectFlags & 0x20000) { if (_partyEffectFlags & 0x20000) {

View file

@ -405,11 +405,13 @@ enum KyraResources {
kEobBaseDscDoorScaleMult5, kEobBaseDscDoorScaleMult5,
kEobBaseDscDoorScaleMult6, kEobBaseDscDoorScaleMult6,
kEobBaseDscDoorType5Offs, kEobBaseDscDoorType5Offs,
kEobBaseDscDoorXE,
kEobBaseDscDoorY1, kEobBaseDscDoorY1,
kEobBaseDscDoorY3, kEobBaseDscDoorY3,
kEobBaseDscDoorY4, kEobBaseDscDoorY4,
kEobBaseDscDoorY5, kEobBaseDscDoorY5,
kEobBaseDscDoorY6, kEobBaseDscDoorY6,
kEobBaseDscDoorY7,
kEobBaseDscDoorCoordsExt, kEobBaseDscDoorCoordsExt,
kEobBaseDscItemPosIndex, kEobBaseDscItemPosIndex,
@ -475,6 +477,7 @@ enum KyraResources {
kEobBaseSpellProperties, kEobBaseSpellProperties,
kEobBaseMagicFlightProps, kEobBaseMagicFlightProps,
kEobBaseTurnUndeadEffect, kEobBaseTurnUndeadEffect,
kEobBaseBurningHandsDest,
kEob1MainMenuStrings, kEob1MainMenuStrings,
kEob1DoorShapeDefs, kEob1DoorShapeDefs,

View file

@ -205,7 +205,7 @@ Common::Error EobCoreEngine::loadGameState(int slot) {
setupCharacterTimers(); setupCharacterTimers();
_screen->loadEobBitmap("CHARGENA", 3, 3); _screen->loadShapeSetBitmap("CHARGENA", 3, 3);
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
EobCharacter *c = &_characters[i]; EobCharacter *c = &_characters[i];
if (!c->flags || c->portrait < 0) if (!c->flags || c->portrait < 0)
@ -213,12 +213,12 @@ Common::Error EobCoreEngine::loadGameState(int slot) {
c->faceShape = _screen->encodeShape((c->portrait % 10) << 2, (c->portrait / 10) << 5, 4, 32, true); 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); _screen->loadShapeSetBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3);
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
EobCharacter *c = &_characters[i]; EobCharacter *c = &_characters[i];
if (!c->flags || c->portrait >= 0) if (!c->flags || c->portrait >= 0)
continue; continue;
c->faceShape = _screen->encodeShape(-(c->portrait + 1), _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true); c->faceShape = _screen->encodeShape((-(c->portrait + 1)) << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true);
} }
_screen->_curPage = 0; _screen->_curPage = 0;

View file

@ -690,7 +690,7 @@ void EobCoreEngine::loadLevel(int level, int sub) {
} }
loadVcnData(gfxFile.c_str(), 0); loadVcnData(gfxFile.c_str(), 0);
_screen->loadEobCpsFileToPage("INVENT", 0, 5, 3, 2); _screen->loadEobBitmap("INVENT", 0, 5, 3, 2);
enableSysTimer(2); enableSysTimer(2);
_sceneDrawPage1 = 2; _sceneDrawPage1 = 2;
@ -734,14 +734,12 @@ Common::String EobCoreEngine::initLevelData(int sub){
pos += 13; pos += 13;
} }
//////// _screen->loadPalette(tmpStr, _screen->getPalette(0));
if (_flags.gameID == GI_EOB1) { if (_flags.gameID == GI_EOB1) {
pos += 11; pos += 11;
_screen->setShapeFadeMode(0, false); _screen->setShapeFadeMode(0, false);
_screen->setShapeFadeMode(1, false); _screen->setShapeFadeMode(1, false);
} }
else
_screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0)); _screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0));
Palette backupPal(256); Palette backupPal(256);
@ -796,8 +794,7 @@ Common::String EobCoreEngine::initLevelData(int sub){
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (_flags.gameID == GI_EOB1) { if (_flags.gameID == GI_EOB1) {
if (*pos == 0xFF) if (*pos != 0xFF)
continue;
loadMonsterShapes((const char *)(pos + 1), i * 18, false, *pos * 18); loadMonsterShapes((const char *)(pos + 1), i * 18, false, *pos * 18);
pos += 13; pos += 13;
} else { } else {
@ -880,7 +877,7 @@ void EobCoreEngine::loadBlockProperties(const char *mazFile) {
} }
void EobCoreEngine::loadDecorations(const char *cpsFile, const char *decFile) { void EobCoreEngine::loadDecorations(const char *cpsFile, const char *decFile) {
_screen->loadEobBitmap(cpsFile, 3, 3); _screen->loadShapeSetBitmap(cpsFile, 3, 3);
Common::SeekableReadStream *s = _res->createReadStream(decFile); Common::SeekableReadStream *s = _res->createReadStream(decFile);
_levelDecorationDataSize = s->readUint16LE(); _levelDecorationDataSize = s->readUint16LE();
@ -1142,7 +1139,10 @@ void EobCoreEngine::drawDecorations(int index) {
int EobCoreEngine::calcNewBlockPositionAndTestPassability(uint16 curBlock, uint16 direction) { int EobCoreEngine::calcNewBlockPositionAndTestPassability(uint16 curBlock, uint16 direction) {
uint16 b = calcNewBlockPosition(curBlock, direction); uint16 b = calcNewBlockPosition(curBlock, direction);
int w = _levelBlockProperties[b].walls[direction ^ 2]; int w = _levelBlockProperties[b].walls[direction ^ 2];
int f = _wllWallFlags[w]; int f = _wllWallFlags[w];
if (!f)
assert (w < (_flags.gameID == GI_EOB1 ? 70 : 80));
if (w == 74 && _currentBlock == curBlock) { if (w == 74 && _currentBlock == curBlock) {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
@ -1163,7 +1163,7 @@ void EobCoreEngine::notifyBlockNotPassable() {
} }
void EobCoreEngine::moveParty(uint16 block) { void EobCoreEngine::moveParty(uint16 block) {
//processMonstersUnk1(); updateAllMonsterDests();
uint16 old = _currentBlock; uint16 old = _currentBlock;
_currentBlock = block; _currentBlock = block;
@ -1176,10 +1176,10 @@ void EobCoreEngine::moveParty(uint16 block) {
runLevelScript(block, 1); runLevelScript(block, 1);
if (_levelBlockProperties[block].walls[0] == 26) if (_flags.gameID == GI_EOB2 && _levelBlockProperties[block].walls[0] == 26)
memset(_levelBlockProperties[block].walls, 0, 4); memset(_levelBlockProperties[block].walls, 0, 4);
//processMonstersUnk1(); updateAllMonsterDests();
_stepCounter++; _stepCounter++;
//_keybControlUnk = -1; //_keybControlUnk = -1;
_sceneUpdateRequired = true; _sceneUpdateRequired = true;
@ -1192,6 +1192,14 @@ int EobCoreEngine::clickedDoorSwitch(uint16 block, uint16 direction) {
SpriteDecoration *d = &_doorSwitches[((v > 12 && v < 23) || v == 31) ? 3 : 0]; SpriteDecoration *d = &_doorSwitches[((v > 12 && v < 23) || v == 31) ? 3 : 0];
int x1 = d->x + _dscShapeCoords[138] - 4; int x1 = d->x + _dscShapeCoords[138] - 4;
int y1 = d->y - 4; int y1 = d->y - 4;
if (_flags.gameID == GI_EOB1 && _currentLevel >= 4 && _currentLevel <= 6) {
if (v >= 30)
x1 += 4;
else
x1 += ((v - _dscDoorXE[v]) * 9);
}
if (!posWithinRect(_mouseX, _mouseY, x1, y1, x1 + (d->shp[2] << 3) + 8, y1 + d->shp[1] + 8) && (_clickedSpecialFlag == 0x40)) if (!posWithinRect(_mouseX, _mouseY, x1, y1, x1 + (d->shp[2] << 3) + 8, y1 + d->shp[1] + 8) && (_clickedSpecialFlag == 0x40))
return clickedDoorNoPry(block, direction); return clickedDoorNoPry(block, direction);

View file

@ -2971,6 +2971,9 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {
} else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) { } else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) {
numCols = stream->size() / Palette::kPC98BytesPerColor; numCols = stream->size() / Palette::kPC98BytesPerColor;
pal.loadPC98Palette(*stream, 0, MIN(maxCols, numCols)); pal.loadPC98Palette(*stream, 0, MIN(maxCols, numCols));
} else if (_vm->gameFlags().gameID == GI_EOB1) {
numCols = stream->size() / Palette::kVGABytesPerColor;
pal.loadVGAPalette7bit(*stream, 0, MIN(maxCols, numCols));
} else { } else {
numCols = stream->size() / Palette::kVGABytesPerColor; numCols = stream->size() / Palette::kVGABytesPerColor;
pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols)); pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols));
@ -3438,6 +3441,18 @@ void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int col
stream.read(_palData + startIndex * 3, colors * 3); stream.read(_palData + startIndex * 3, colors * 3);
} }
void Palette::loadVGAPalette7bit(Common::ReadStream &stream, int startIndex, int colors) {
assert(startIndex + colors <= _numColors);
stream.read(_palData + startIndex * 3, colors * 3);
uint8 *pos = _palData + startIndex * 3;
for (int i = 0 ; i < colors; i++) {
*pos++ &= 0x3f;
*pos++ &= 0x3f;
*pos++ &= 0x3f;
}
}
void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors) { void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int colors) {
assert(startIndex + colors <= _numColors); assert(startIndex + colors <= _numColors);

View file

@ -251,6 +251,11 @@ public:
*/ */
void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors); void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors);
/**
* Load a VGA palette from the given stream masking out the upper bit.
*/
void loadVGAPalette7bit(Common::ReadStream &stream, int startIndex, int colors);
/** /**
* Load a AMIGA palette from the given stream. * Load a AMIGA palette from the given stream.
*/ */

View file

@ -145,12 +145,15 @@ void Screen_Eob::printShadedText(const char *string, int x, int y, int col1, int
printText(string, x, y, col1, 0); printText(string, x, y, col1, 0);
} }
void Screen_Eob::loadEobBitmap(const char *file, int tempPage, int destPage) { void Screen_Eob::loadShapeSetBitmap(const char *file, int tempPage, int destPage) {
loadEobCpsFileToPage(file, 0, tempPage, destPage, -1); loadEobBitmap(file, 0, tempPage, destPage, -1);
_curPage = 2; _curPage = 2;
} }
void Screen_Eob::loadEobCpsFileToPage(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage) { void Screen_Eob::loadEobBitmap(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage) {
//Common::String tmp = file;
//if (_vm->game() == GI_EOB1 && tmp.equalsIgnoreCase("spider"))
// tmp += "1";
Common::String tmp = Common::String::format("%s.CPS", file); Common::String tmp = Common::String::format("%s.CPS", file);
Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp); Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp);
bool loadAlternative = false; bool loadAlternative = false;
@ -170,7 +173,7 @@ void Screen_Eob::loadEobCpsFileToPage(const char *file, const uint8 *ditheringDa
tmp.setChar('X', 0); tmp.setChar('X', 0);
s = _vm->resource()->createReadStream(tmp); s = _vm->resource()->createReadStream(tmp);
if (!s) if (!s)
error("Screen_Eob::loadEobCpsFileToPage(): CPS file loading failed."); error("Screen_Eob::loadEobBitmap(): CPS file loading failed.");
s->seek(768); s->seek(768);
loadFileDataToPage(s, destPage, 64000); loadFileDataToPage(s, destPage, 64000);
delete s; delete s;

View file

@ -51,8 +51,8 @@ public:
void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size); void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size);
void printShadedText(const char *string, int x, int y, int col1, int col2); 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, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage);
void loadEobBitmap(const char *file, int tempPage, int destPage); void loadShapeSetBitmap(const char *file, int tempPage, int destPage);
uint8 *encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool flag = false); 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, ...); void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd = -1, int flags = 0, ...);

View file

@ -54,7 +54,7 @@ const uint8 *EobCoreEngine::initScriptTimers(const uint8 *pos) {
while (((int16)READ_LE_UINT16(pos)) != -1) { while (((int16)READ_LE_UINT16(pos)) != -1) {
_scriptTimers[_scriptTimersCount].func = READ_LE_UINT16(pos); _scriptTimers[_scriptTimersCount].func = READ_LE_UINT16(pos);
pos += 2; pos += 2;
uint16 ticks = (int16)READ_LE_UINT16(pos) * 18; uint16 ticks = READ_LE_UINT16(pos) * 18;
_scriptTimers[_scriptTimersCount].ticks = ticks; _scriptTimers[_scriptTimersCount].ticks = ticks;
pos += 2; pos += 2;
_scriptTimers[_scriptTimersCount++].next = _system->getMillis() + ticks * _tickLength; _scriptTimers[_scriptTimersCount++].next = _system->getMillis() + ticks * _tickLength;
@ -64,20 +64,26 @@ const uint8 *EobCoreEngine::initScriptTimers(const uint8 *pos) {
} }
void EobCoreEngine::updateScriptTimers() { void EobCoreEngine::updateScriptTimers() {
if ((_scriptTimersMode & 1) && _stepsUntilScriptCall && _stepCounter > _stepsUntilScriptCall) { bool timerUpdate = false;
if ((_scriptTimersMode & 2) && _stepsUntilScriptCall && _stepCounter > _stepsUntilScriptCall) {
_inf->run(0, 0x20); _inf->run(0, 0x20);
_stepCounter = 0; _stepCounter = 0;
timerUpdate = true;
} }
if (_scriptTimersMode & 2) { if (_scriptTimersMode & 1) {
for (int i = 0; i < _scriptTimersCount; i++) { for (int i = 0; i < _scriptTimersCount; i++) {
if (_scriptTimers[i].next < _system->getMillis()) { if (_scriptTimers[i].next < _system->getMillis()) {
_inf->run(_scriptTimers[i].func, _flags.gameID == GI_EOB1 ? 0x20 : 0x80); _inf->run(_scriptTimers[i].func, _flags.gameID == GI_EOB1 ? 0x20 : 0x80);
_scriptTimers[i].next = _system->getMillis() + _scriptTimers[i].ticks * _tickLength; _scriptTimers[i].next = _system->getMillis() + _scriptTimers[i].ticks * _tickLength;
_sceneUpdateRequired = true; _sceneUpdateRequired = true;
timerUpdate = true;
} }
} }
} }
if (timerUpdate)
updateScriptTimersExtra();
} }
EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _vm(engine), _screen(screen), EobInfProcessor::EobInfProcessor(EobCoreEngine *engine, Screen_Eob *screen) : _vm(engine), _screen(screen),
@ -211,13 +217,13 @@ bool EobInfProcessor::preventRest() const {
void EobInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in) { void EobInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in) {
_preventRest = in.readByte(); _preventRest = in.readByte();
for (int i = 0; i < 18; i++) for (int i = 0; i < 18; i++)
_flagTable[i] = in.readUint16BE(); _flagTable[i] = in.readUint32BE();
} }
void EobInfProcessor::saveState(Common::OutSaveFile *out) { void EobInfProcessor::saveState(Common::OutSaveFile *out) {
out->writeByte(_preventRest); out->writeByte(_preventRest);
for (int i = 0; i < 18; i++) for (int i = 0; i < 18; i++)
out->writeUint16BE(_flagTable[i]); out->writeUint32BE(_flagTable[i]);
} }
const char *EobInfProcessor::getString(uint16 index) { const char *EobInfProcessor::getString(uint16 index) {

View file

@ -43,7 +43,7 @@ int EobEngine::mainMenu() {
switch (menuChoice) { switch (menuChoice) {
case 0: case 0:
_screen->loadPalette("EOBPAL.COL", _screen->getPalette(0)); _screen->loadPalette("EOBPAL.COL", _screen->getPalette(0));
_screen->loadEobCpsFileToPage("INTRO", 0, 5, 3, 2); _screen->loadEobBitmap("INTRO", 0, 5, 3, 2);
_screen->setScreenPalette(_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0));
_screen->_curPage = 2; _screen->_curPage = 2;
of = _screen->setFont(Screen::FID_6_FNT); of = _screen->setFont(Screen::FID_6_FNT);
@ -107,6 +107,7 @@ void EobEngine::seq_playOpeningCredits() {
static const char *cmpList[] = { "WESTWOOD.CMP", "AND.CMP", "SSI.CMP", "PRESENT.CMP", "DAND.CMP" }; static const char *cmpList[] = { "WESTWOOD.CMP", "AND.CMP", "SSI.CMP", "PRESENT.CMP", "DAND.CMP" };
static const uint8 frameDelay[] = { 140, 50, 100, 50, 140 }; static const uint8 frameDelay[] = { 140, 50, 100, 50, 140 };
_allowSkip = true;
_screen->loadPalette("WESTWOOD.COL", _screen->getPalette(0)); _screen->loadPalette("WESTWOOD.COL", _screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0));
@ -125,14 +126,21 @@ void EobEngine::seq_playOpeningCredits() {
} }
delay(50 * _tickLength); delay(50 * _tickLength);
_allowSkip = false;
} }
void EobEngine::seq_playIntro() { void EobEngine::seq_playIntro() {
_allowSkip = true;
//_sound->playTrack(2); //_sound->playTrack(2);
_allowSkip = false;
} }
void EobEngine::seq_playFinale() { void EobEngine::seq_playFinale() {
_allowSkip = true;
_allowSkip = false;
} }
} // End of namespace Kyra } // End of namespace Kyra

View file

@ -941,6 +941,7 @@ DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine *
_system->delayMillis(150); _system->delayMillis(150);
_vm->resetSkipFlag(true); _vm->resetSkipFlag(true);
_vm->_allowSkip = true;
} }
DarkmoonSequenceHelper::~DarkmoonSequenceHelper() { DarkmoonSequenceHelper::~DarkmoonSequenceHelper() {
@ -960,6 +961,7 @@ DarkmoonSequenceHelper::~DarkmoonSequenceHelper() {
_system->delayMillis(150); _system->delayMillis(150);
_vm->resetSkipFlag(true); _vm->resetSkipFlag(true);
_vm->_allowSkip = false;
} }
void DarkmoonSequenceHelper::loadScene(int index, int pageNum) { void DarkmoonSequenceHelper::loadScene(int index, int pageNum) {

View file

@ -54,7 +54,11 @@ int LolEobBaseEngine::getBlockDistance(uint16 block1, uint16 block2) {
namespace Kyra { namespace Kyra {
void EobCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) { void EobCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) {
_screen->loadEobBitmap(filename, 3, 3); Common::String s = _flags.gameID == GI_EOB1 && !scumm_stricmp(filename, "spider") ? "spider1" : filename;
if (GI_EOB1 && !scumm_stricmp(filename, "rust"))
s += "1";
_screen->loadShapeSetBitmap(s.c_str(), 3, 3);
const uint16 *enc = &_encodeMonsterShpTable[encodeTableIndex << 2]; const uint16 *enc = &_encodeMonsterShpTable[encodeTableIndex << 2];
for (int i = 0; i < 6; i++, enc += 4) for (int i = 0; i < 6; i++, enc += 4)
@ -275,14 +279,14 @@ void EobCoreEngine::updateAttackingMonsterFlags() {
} }
const int8 *EobCoreEngine::getMonsterBlockPositions(uint16 block) { const int8 *EobCoreEngine::getMonsterBlockPositions(uint16 block) {
static int8 pos[6]; memset(_monsterBlockPosArray, -1, sizeof(_monsterBlockPosArray));
memset(pos, -1, sizeof(pos));
for (int8 i = 0; i < 30; i++) { for (int8 i = 0; i < 30; i++) {
if (_monsters[i].block != block) if (_monsters[i].block != block)
continue; continue;
pos[_monsters[i].pos] = i; assert(_monsters[i].pos < sizeof(_monsterBlockPosArray));
_monsterBlockPosArray[_monsters[i].pos] = i;
} }
return pos; return _monsterBlockPosArray;
} }
int EobCoreEngine::getClosestMonsterPos(int charIndex, int block) { int EobCoreEngine::getClosestMonsterPos(int charIndex, int block) {
@ -770,6 +774,11 @@ void EobCoreEngine::updateMonsterDest2(EobMonsterInPlay *m) {
m->dest = _currentBlock; m->dest = _currentBlock;
} }
void EobCoreEngine::updateAllMonsterDests() {
for (int i = 0; i < 30; i++)
updateMonsterDest(&_monsters[i]);
}
void EobCoreEngine::turnFriendlyMonstersHostile() { void EobCoreEngine::turnFriendlyMonstersHostile() {
EobMonsterInPlay *m = 0; EobMonsterInPlay *m = 0;
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {

View file

@ -448,7 +448,7 @@ void EobCoreEngine::initStaticResource() {
_npcPreset = _staticres->loadEobNpcData(kEobBaseNpcPresets, temp); _npcPreset = _staticres->loadEobNpcData(kEobBaseNpcPresets, temp);
_teleporterShapeCoords = _staticres->loadRawData(kEobBaseDscTelptrShpCoords, temp); _teleporterShapeCoords = _staticres->loadRawData(kEobBaseDscTelptrShpCoords, temp);
_portalSeq = _staticres->loadRawData(kEobBasePortalSeqData, temp); _portalSeq = (const int8*)_staticres->loadRawData(kEobBasePortalSeqData, temp);
_mnDef = _staticres->loadRawData(kEobBaseManDef, temp); _mnDef = _staticres->loadRawData(kEobBaseManDef, temp);
_mnWord = _staticres->loadStrings(kEobBaseManWord, _mnNumWord); _mnWord = _staticres->loadStrings(kEobBaseManWord, _mnNumWord);
_mnPrompt = _staticres->loadStrings(kEobBaseManPrompt, temp); _mnPrompt = _staticres->loadStrings(kEobBaseManPrompt, temp);
@ -493,6 +493,7 @@ void EobCoreEngine::initStaticResource() {
_dscDoorScaleMult2 = _staticres->loadRawData(kEobBaseDscDoorScaleMult2, temp); _dscDoorScaleMult2 = _staticres->loadRawData(kEobBaseDscDoorScaleMult2, temp);
_dscDoorScaleMult3 = _staticres->loadRawData(kEobBaseDscDoorScaleMult3, temp); _dscDoorScaleMult3 = _staticres->loadRawData(kEobBaseDscDoorScaleMult3, temp);
_dscDoorY1 = _staticres->loadRawData(kEobBaseDscDoorY1, temp); _dscDoorY1 = _staticres->loadRawData(kEobBaseDscDoorY1, temp);
_dscDoorXE = _staticres->loadRawData(kEobBaseDscDoorXE, temp);
_dscItemPosIndex= _staticres->loadRawData(kEobBaseDscItemPosIndex, temp); _dscItemPosIndex= _staticres->loadRawData(kEobBaseDscItemPosIndex, temp);
_dscItemShpX = (const int16*)_staticres->loadRawDataBe16(kEobBaseDscItemShpX, temp); _dscItemShpX = (const int16*)_staticres->loadRawDataBe16(kEobBaseDscItemShpX, temp);
@ -533,6 +534,7 @@ void EobCoreEngine::initStaticResource() {
_sparkEffectOfY = _staticres->loadRawData(kEobBaseSparkOfY, temp); _sparkEffectOfY = _staticres->loadRawData(kEobBaseSparkOfY, temp);
_magicFlightObjectProperties = _staticres->loadRawData(kEobBaseMagicFlightProps, temp); _magicFlightObjectProperties = _staticres->loadRawData(kEobBaseMagicFlightProps, temp);
_turnUndeadEffect = _staticres->loadRawData(kEobBaseTurnUndeadEffect, temp); _turnUndeadEffect = _staticres->loadRawData(kEobBaseTurnUndeadEffect, temp);
_burningHandsDest = _staticres->loadRawData(kEobBaseBurningHandsDest, temp);
// Hard code the following strings, since EOB I doesn't have them in the original. // Hard code the following strings, since EOB I doesn't have them in the original.
// EOB I doesn't have load and save menus, because there is only one single // EOB I doesn't have load and save menus, because there is only one single
@ -1002,7 +1004,8 @@ void EobCoreEngine::initSpells() {
ec2(empty); ec2(empty);
ec(empty); ec(empty);
ec2(empty); ec2(empty);
ec(unk1Passive); ec1(kuotoaAttack);
ec2(unk1Passive);
ec2(empty); ec2(empty);
ec2(unk2Passive); ec2(unk2Passive);
ec(deathSpellPassive); ec(deathSpellPassive);
@ -1064,6 +1067,7 @@ void EobEngine::initStaticResource() {
_dscDoorY4 = _staticres->loadRawData(kEobBaseDscDoorY4, temp); _dscDoorY4 = _staticres->loadRawData(kEobBaseDscDoorY4, temp);
_dscDoorY5 = _staticres->loadRawData(kEobBaseDscDoorY5, temp); _dscDoorY5 = _staticres->loadRawData(kEobBaseDscDoorY5, temp);
_dscDoorY6 = _staticres->loadRawData(kEobBaseDscDoorY6, temp); _dscDoorY6 = _staticres->loadRawData(kEobBaseDscDoorY6, temp);
_dscDoorY7 = _staticres->loadRawData(kEobBaseDscDoorY7, temp);
_dscDoorCoordsExt = (const int16*)_staticres->loadRawDataBe16(kEobBaseDscDoorCoordsExt, temp); _dscDoorCoordsExt = (const int16*)_staticres->loadRawDataBe16(kEobBaseDscDoorCoordsExt, temp);
_monsterDistAttType10 = _staticres->loadRawData(kEob1MonsterDistAttType10, temp); _monsterDistAttType10 = _staticres->loadRawData(kEob1MonsterDistAttType10, temp);

View file

@ -210,7 +210,7 @@ void EobCoreEngine::advanceTimers(uint32 millis) {
setupCharacterTimers(); setupCharacterTimers();
if (_scriptTimersMode & 2) { if (_scriptTimersMode & 1) {
for (int i = 0; i < _scriptTimersCount; i++) { for (int i = 0; i < _scriptTimersCount; i++) {
if (_scriptTimers[i].next > ct) { if (_scriptTimers[i].next > ct) {
uint32 chrt = _scriptTimers[i].next - ct; uint32 chrt = _scriptTimers[i].next - ct;
@ -371,7 +371,7 @@ void EobCoreEngine::timerUpdateTeleporters(int timerNum) {
_teleporterPulse ^= 1; _teleporterPulse ^= 1;
for (int i = 0; i < 18; i++) { for (int i = 0; i < 18; i++) {
uint8 w = _visibleBlocks[i]->walls[_sceneDrawVarDown]; uint8 w = _visibleBlocks[i]->walls[_sceneDrawVarDown];
if (w == 44 || w == 74) { if ((_flags.gameID == GI_EOB1 && w == 52) || (_flags.gameID == GI_EOB2 && (w == 44 || w == 74))) {
_sceneUpdateRequired = true; _sceneUpdateRequired = true;
return; return;
} }