From b288889c978990423b08dad8f838d891610f36b5 Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 15 Aug 2011 01:43:26 +0200 Subject: [PATCH] KYRA: (EOB) - implement wall of force spell --- devtools/create_kyradat/create_kyradat.cpp | 15 ++++++ devtools/create_kyradat/create_kyradat.h | 6 +++ devtools/create_kyradat/games.cpp | 5 ++ devtools/create_kyradat/tables.cpp | 31 +++++++++++ dists/engine-data/kyra.dat | Bin 464892 -> 465075 bytes engines/kyra/eobcommon.cpp | 9 +++- engines/kyra/eobcommon.h | 19 +++++++ engines/kyra/loleobbase.h | 4 ++ engines/kyra/magic_eob.cpp | 59 ++++++++++++++++++--- engines/kyra/resource.h | 6 +++ engines/kyra/saveload_eob.cpp | 53 +++++++++++++++--- engines/kyra/scene_eob.cpp | 7 ++- engines/kyra/script_eob.cpp | 12 ++--- engines/kyra/sequences_eob2.cpp | 20 +++---- engines/kyra/sprites_eob.cpp | 17 ++++++ engines/kyra/staticres_eob.cpp | 6 +++ engines/kyra/timer_eob.cpp | 2 +- 17 files changed, 235 insertions(+), 36 deletions(-) diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp index a8531dd470c..069118bdabe 100644 --- a/devtools/create_kyradat/create_kyradat.cpp +++ b/devtools/create_kyradat/create_kyradat.cpp @@ -571,6 +571,11 @@ const ExtractFilename extractFilenames[] = { { kEob2DranFoolsStrings, kTypeStringList, true }, { kEob2HornStrings, kTypeStringList, true }, { kEob2HornSounds, kTypeRawData, false }, + { kEob2WallOfForceDsX, kLolTypeRaw16, false }, + { kEob2WallOfForceDsY, kTypeRawData, false }, + { kEob2WallOfForceNumW, kTypeRawData, false }, + { kEob2WallOfForceNumH, kTypeRawData, false }, + { kEob2WallOfForceShpId, kTypeRawData, false }, // LANDS OF LORE @@ -1986,6 +1991,16 @@ const char *getIdString(const int id) { return "kEob2HornStrings"; case kEob2HornSounds: return "kEob2HornSounds"; + case kEob2WallOfForceDsX: + return "kEob2WallOfForceDsX"; + case kEob2WallOfForceDsY: + return "kEob2WallOfForceDsY"; + case kEob2WallOfForceNumW: + return "kEob2WallOfForceNumW"; + case kEob2WallOfForceNumH: + return "kEob2WallOfForceNumH"; + case kEob2WallOfForceShpId: + return "kEob2WallOfForceShpId"; case kLolIngamePakFiles: return "kLolIngamePakFiles"; case kLolCharacterDefs: diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h index 44fa93a1746..c7a29fb99a3 100644 --- a/devtools/create_kyradat/create_kyradat.h +++ b/devtools/create_kyradat/create_kyradat.h @@ -553,6 +553,12 @@ enum kExtractID { kEob2HornStrings, kEob2HornSounds, + kEob2WallOfForceDsX, + kEob2WallOfForceDsY, + kEob2WallOfForceNumW, + kEob2WallOfForceNumH, + kEob2WallOfForceShpId, + kLolIngamePakFiles, kLolCharacterDefs, kLolIngameSfxFiles, diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp index 9ecbf0144c3..d5b5c29aa99 100644 --- a/devtools/create_kyradat/games.cpp +++ b/devtools/create_kyradat/games.cpp @@ -1595,6 +1595,11 @@ const int eob2FloppyNeed[] = { kEob2DranFoolsStrings, kEob2HornStrings, kEob2HornSounds, + kEob2WallOfForceDsX, + kEob2WallOfForceDsY, + kEob2WallOfForceNumW, + kEob2WallOfForceNumH, + kEob2WallOfForceShpId, kLolEobCommonDscShapeIndex, kLolEobCommonDscX, diff --git a/devtools/create_kyradat/tables.cpp b/devtools/create_kyradat/tables.cpp index ab75baf91ca..0b249247d8e 100644 --- a/devtools/create_kyradat/tables.cpp +++ b/devtools/create_kyradat/tables.cpp @@ -3195,6 +3195,32 @@ const ExtractEntrySearchData kEob2HornSoundsProvider[] = { EXTRACT_END_ENTRY }; +const ExtractEntrySearchData kEob2WallOfForceDsXProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000024, 0x00000D67, { { 0x51, 0xCF, 0xAB, 0x1E, 0xB4, 0xE0, 0xE3, 0x44, 0x29, 0xD1, 0xDC, 0x82, 0xCD, 0x08, 0x50, 0xF5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob2WallOfForceDsYProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000003, 0x00000048, { { 0x45, 0xFC, 0xEA, 0x8C, 0x34, 0xD7, 0xBE, 0x74, 0x05, 0x03, 0xE6, 0x94, 0x34, 0xB5, 0x45, 0x4D } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob2WallOfForceNumWProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000003, 0x00000006, { { 0x52, 0x89, 0xDF, 0x73, 0x7D, 0xF5, 0x73, 0x26, 0xFC, 0xDD, 0x22, 0x59, 0x7A, 0xFB, 0x1F, 0xAC } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob2WallOfForceNumHProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000003, 0x00000011, { { 0x33, 0x86, 0x06, 0xBE, 0x8D, 0xC8, 0x37, 0x2D, 0x0F, 0x61, 0x97, 0xA4, 0x26, 0xA9, 0xBC, 0x60 } } } }, + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kEob2WallOfForceShpIdProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000003, 0x00000006, { { 0x77, 0xAE, 0x9B, 0x52, 0x9E, 0xF7, 0xEB, 0x48, 0xA8, 0x5E, 0xED, 0xC2, 0x08, 0x53, 0xCE, 0x3C } } } }, + EXTRACT_END_ENTRY +}; + const ExtractEntrySearchData kLolIngamePakFilesProvider[] = { { UNK_LANG, kPlatformPC, { 0x00000088, 0x0000224F, { { 0xDA, 0x24, 0x18, 0xA3, 0xEF, 0x16, 0x70, 0x8F, 0xA8, 0xC2, 0x2E, 0xC2, 0xED, 0x39, 0x03, 0xD1 } } } }, { UNK_LANG, kPlatformPC98, { 0x00000084, 0x00002125, { { 0x7A, 0x89, 0xE2, 0x36, 0xEC, 0x6F, 0x52, 0x2B, 0xEF, 0xBA, 0x3D, 0x28, 0x54, 0xDA, 0xFB, 0x72 } } } }, @@ -4162,6 +4188,11 @@ const ExtractEntry extractProviders[] = { { kEob2DranFoolsStrings, kEob2DranFoolsStringsProvider }, { kEob2HornStrings, kEob2HornStringsProvider }, { kEob2HornSounds, kEob2HornSoundsProvider }, + { kEob2WallOfForceDsX, kEob2WallOfForceDsXProvider }, + { kEob2WallOfForceDsY, kEob2WallOfForceDsYProvider }, + { kEob2WallOfForceNumW, kEob2WallOfForceNumWProvider }, + { kEob2WallOfForceNumH, kEob2WallOfForceNumHProvider }, + { kEob2WallOfForceShpId, kEob2WallOfForceShpIdProvider }, { kLolIngamePakFiles, kLolIngamePakFilesProvider }, { kLolCharacterDefs, kLolCharacterDefsProvider }, diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat index aa3d62b84d0bf0065d4605811ac139826d612156..35aff97dde9dd65659b6096be221df2bfd6eb7af 100644 GIT binary patch delta 26970 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, 0, _itemIconShapes[0]); - _screen->showMouse(); loadItemDefs(); int action = 0; @@ -363,6 +368,7 @@ Common::Error EobCoreEngine::go() { startupLoad(); _gameToLoad = -1; } else { + _screen->showMouse(); action = mainMenu(); } @@ -453,6 +459,7 @@ void EobCoreEngine::runLoop() { _timer->update(); updateScriptTimers(); + updateWallOfForceTimers(); if (_sceneUpdateRequired) drawScene(1); diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index 51dfb8b726d..ffc951e80da 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -561,6 +561,12 @@ protected: const uint16 *_encodeMonsterShpTable; const uint8 _teleporterWallId; + const int16 *_wallOfForceDsX; + const uint8 *_wallOfForceDsY; + const uint8 *_wallOfForceDsNumW; + const uint8 *_wallOfForceDsNumH; + const uint8 *_wallOfForceShpId; + const int8 *_monsterDirChangeTable; // Level @@ -833,6 +839,9 @@ protected: void *generateMonsterTempData(LevelTempData *tmp); void restoreMonsterTempData(LevelTempData *tmp); void releaseMonsterTempData(LevelTempData *tmp); + void *generateWallOfForceTempData(LevelTempData *tmp); + void restoreWallOfForceTempData(LevelTempData *tmp); + void releaseWallOfForceTempData(LevelTempData *tmp); const char * const *_saveLoadStrings; @@ -920,6 +929,9 @@ protected: Item createMagicWeaponItem(int flags, int icon, int value, int type); void removeMagicWeaponItem(Item item); + void updateWallOfForceTimers(); + void destroyWallOfForce(int index); + int findSingleSpellTarget(int dist); int findFirstCharacterSpellTarget(); @@ -1031,6 +1043,13 @@ protected: EobSpell *_spells; int _numSpells; + struct WallOfForce { + uint16 block; + uint32 duration; + }; + + WallOfForce *_wallsOfForce; + const char *const *_bookNumbers; const char *const *_mageSpellList; int _mageSpellListSize; diff --git a/engines/kyra/loleobbase.h b/engines/kyra/loleobbase.h index ba59fe796b0..02b236d44fd 100644 --- a/engines/kyra/loleobbase.h +++ b/engines/kyra/loleobbase.h @@ -60,6 +60,7 @@ struct LevelTempData { uint16 *flags; void *monsters; void *flyingObjects; + void *wallsOfForce; uint8 monsterDifficulty; }; @@ -315,6 +316,9 @@ protected: void restoreFlyingObjectTempData(LevelTempData *tmp); void *generateFlyingObjectTempData(LevelTempData *tmp); void releaseFlyingObjectTempData(LevelTempData *tmp); + virtual void *generateWallOfForceTempData(LevelTempData *tmp) { return 0; } + virtual void restoreWallOfForceTempData(LevelTempData *tmp) {} + virtual void releaseWallOfForceTempData(LevelTempData *tmp) {} LevelTempData *_lvlTempData[29]; const int _numFlyingObjects; diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index 2ad0da72583..646d3897065 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -24,6 +24,7 @@ #include "kyra/eobcommon.h" #include "kyra/resource.h" +#include "common/system.h" namespace Kyra { @@ -490,11 +491,11 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d int blockDamage = fo->flags & 2; int hitTest = fo->flags & 4; - int s = 5; - int dmgType = 3; + int savingThrowType = 5; + int savingThrowEffect = 3; if (fo->flags & 8) { - s = 4; - dmgType = 0; + savingThrowType = 4; + savingThrowEffect = 0; } int dmgFlag = _spells[fo->callBackIndex].damageFlags; @@ -516,7 +517,7 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d continue; } - calcAndInflictMonsterDamage(&_monsters[*m], 0, 0, dmg, dmgFlag, s, dmgType); + calcAndInflictMonsterDamage(&_monsters[*m], 0, 0, dmg, dmgFlag, savingThrowType, savingThrowEffect); res = true; } updateAllMonsterShapes(); @@ -532,7 +533,7 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d int dmg = rollDice(dcTimes, dcPips, dcOffs) * level; res = true; - calcAndInflictCharacterDamage(i, 0, 0, dmg, dmgFlag, s, dmgType); + calcAndInflictCharacterDamage(i, 0, 0, dmg, dmgFlag, savingThrowType, savingThrowEffect); } } else { int c = _dscItemPosIndex[(_currentDirection << 2) + (fo->curPos & 3)]; @@ -545,7 +546,7 @@ bool EobCoreEngine::magicObjectDamageHit(EobFlyingObject *fo, int dcTimes, int d 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); + calcAndInflictCharacterDamage(c, 0, 0, dmg, dmgFlag, savingThrowType, savingThrowEffect); } } } @@ -708,6 +709,22 @@ void EobCoreEngine::removeMagicWeaponItem(Item item) { _items[item].level = -1; } +void EobCoreEngine::updateWallOfForceTimers() { + uint32 ct = _system->getMillis(); + for (int i = 0; i < 5; i++) { + if (!_wallsOfForce[i].block) + continue; + if (_wallsOfForce[i].duration < ct) + destroyWallOfForce(i); + } +} + +void EobCoreEngine::destroyWallOfForce(int index) { + memset(_levelBlockProperties[_wallsOfForce[index].block].walls, 0, 4); + _wallsOfForce[index].block = 0; + _sceneUpdateRequired = true; +} + int EobCoreEngine::findSingleSpellTarget(int dist) { uint16 bl = _currentBlock; int res = -1; @@ -924,7 +941,7 @@ void EobCoreEngine::spellCallback_start_vampiricTouch() { Item i = (t != -1) ? createMagicWeaponItem(0x18, 83, 0, t) : -1; if (t == -1 || i == -1) { if (_flags.gameID == GI_EOB2) - printWarning(_magicStrings8[0]); + printWarning(_magicStrings8[2]); removeCharacterEffect(_activeSpell, _activeSpellCharId, 0); deleteCharEventTimer(_activeSpellCharId, -_activeSpell); _returnAfterSpellCallback = true; @@ -1019,7 +1036,33 @@ bool EobCoreEngine::spellCallback_end_holdMonster(void *obj) { } void EobCoreEngine::spellCallback_start_wallOfForce() { + uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection); + LevelBlockProperty *l = &_levelBlockProperties[bl]; + if (l->walls[0] || l->walls[1] || l->walls[2] || l->walls[3] || (l->flags & 7)) { + printWarning(_magicStrings8[3]); + return; + } + uint32 dur = 0xffffffff; + int s = 0; + int i = 0; + + for (; i < 5; i++) { + if (!_wallsOfForce[i].block) + break; + if (_wallsOfForce[i].duration < dur) { + dur = _wallsOfForce[i].duration; + s = i; + } + } + + if (i == 5) + destroyWallOfForce(s); + + memset(_levelBlockProperties[bl].walls, 74, 4); + _wallsOfForce[s].block = bl; + _wallsOfForce[s].duration = _system->getMillis() + (((getMageLevel(_openBookChar) * 546) >> 1) + 546) * _tickLength; + _sceneUpdateRequired = true; } void EobCoreEngine::spellCallback_start_disintegrate() { diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 5ed658ccee5..f330d42004a 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -627,6 +627,12 @@ enum KyraResources { kEob2HornStrings, kEob2HornSounds, + kEob2WallOfForceDsX, + kEob2WallOfForceDsY, + kEob2WallOfForceNumW, + kEob2WallOfForceNumH, + kEob2WallOfForceShpId, + kLolIngamePakFiles, kLolCharacterDefs, kLolIngameSfxFiles, diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp index 05eea820bb5..24a10133d09 100644 --- a/engines/kyra/saveload_eob.cpp +++ b/engines/kyra/saveload_eob.cpp @@ -72,6 +72,7 @@ void LolEobBaseEngine::generateTempData() { _lvlTempData[l]->monsters = generateMonsterTempData(_lvlTempData[l]); _lvlTempData[l]->flyingObjects = generateFlyingObjectTempData(_lvlTempData[l]); + _lvlTempData[l]->wallsOfForce = generateWallOfForceTempData(_lvlTempData[l]); _hasTempDataFlags |= (1 << l); delete[] p2; @@ -104,6 +105,7 @@ void LolEobBaseEngine::restoreBlockTempData(int levelIndex) { restoreMonsterTempData(_lvlTempData[l]); restoreFlyingObjectTempData(_lvlTempData[l]); + restoreWallOfForceTempData(_lvlTempData[l]); delete[] p2; } @@ -115,6 +117,7 @@ void LolEobBaseEngine::releaseTempData() { delete[] _lvlTempData[i]->flags; releaseMonsterTempData(_lvlTempData[i]); releaseFlyingObjectTempData(_lvlTempData[i]); + releaseWallOfForceTempData(_lvlTempData[i]); delete _lvlTempData[i]; _lvlTempData[i] = 0; } @@ -293,13 +296,15 @@ Common::Error EobCoreEngine::loadGameState(int slot) { } _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[_numFlyingObjects]; - _lvlTempData[i]->flyingObjects = lf; LevelTempData *l = _lvlTempData[i]; + l->wallsXorData = new uint8[4096]; + l->flags = new uint16[1024]; + EobMonsterInPlay *lm = new EobMonsterInPlay[30]; + l->monsters = lm; + EobFlyingObject *lf = new EobFlyingObject[_numFlyingObjects]; + l->flyingObjects = lf; + WallOfForce *lw = new WallOfForce[5]; + l->wallsOfForce = lw; in.read(l->wallsXorData, 4096); for (int ii = 0; ii < 1024; ii++) @@ -349,10 +354,14 @@ Common::Error EobCoreEngine::loadGameState(int slot) { m->flags = in.readByte(); m->unused = in.readByte(); } + + for (int ii = 0; ii < 5; ii++) { + WallOfForce *w = &lw[ii]; + w->block = in.readUint16BE(); + w->duration = in.readUint32BE(); + } } - if (_flags.gameID == GI_EOB1) - _screen->loadPalette("EOBPAL.COL", _screen->getPalette(0)); loadLevel(_currentLevel, _currentSub); _sceneUpdateRequired = true; _screen->setFont(Screen::FID_6_FNT); @@ -515,6 +524,7 @@ Common::Error EobCoreEngine::saveGameStateIntern(int slot, const char *saveName, EobMonsterInPlay *lm = (EobMonsterInPlay*)_lvlTempData[i]->monsters; EobFlyingObject *lf = (EobFlyingObject*)_lvlTempData[i]->flyingObjects; + WallOfForce *lw = (WallOfForce*)_lvlTempData[i]->wallsOfForce; for (int ii = 0; ii < 30; ii++) { EobMonsterInPlay *m = &lm[ii]; @@ -560,6 +570,12 @@ Common::Error EobCoreEngine::saveGameStateIntern(int slot, const char *saveName, out->writeByte(m->flags); out->writeByte(m->unused); } + + for (int ii = 0; ii < 5; ii++) { + WallOfForce *w = &lw[ii]; + out->writeUint16BE(w->block); + out->writeUint32BE(w->duration); + } } out->finalize(); @@ -591,6 +607,27 @@ void EobCoreEngine::releaseMonsterTempData(LevelTempData *tmp) { delete[] p; } +void *EobCoreEngine::generateWallOfForceTempData(LevelTempData *tmp) { + WallOfForce *w = new WallOfForce[5]; + memcpy(w, _wallsOfForce, sizeof(WallOfForce) * 5); + uint32 ct = _system->getMillis(); + for (int i = 0; i < 5; i++) + w[i].duration = (w[i].duration > ct) ? w[i].duration - ct : _tickLength; + return w; +} + +void EobCoreEngine::restoreWallOfForceTempData(LevelTempData *tmp) { + memcpy(_wallsOfForce, tmp->wallsOfForce, sizeof(WallOfForce) * 5); + uint32 ct = _system->getMillis(); + for (int i = 0; i < 5; i++) + _wallsOfForce[i].duration += ct; +} + +void EobCoreEngine::releaseWallOfForceTempData(LevelTempData *tmp) { + WallOfForce *p = (WallOfForce*)tmp->wallsOfForce; + delete[] p; +} + #endif // ENABLE_EOB } // End of namespace Kyra diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp index aef131f6cb2..afce9efdfa0 100644 --- a/engines/kyra/scene_eob.cpp +++ b/engines/kyra/scene_eob.cpp @@ -1144,9 +1144,12 @@ int EobCoreEngine::calcNewBlockPositionAndTestPassability(uint16 curBlock, uint1 if (!f) assert((_flags.gameID == GI_EOB1 && w < 70) || (_flags.gameID == GI_EOB2 && w < 80)); - if (w == 74 && _currentBlock == curBlock) { + if (_flags.gameID == GI_EOB2 && w == 74 && _currentBlock == curBlock) { for (int i = 0; i < 5; i++) { - + if (_wallsOfForce[i].block == b) { + destroyWallOfForce(i); + f = _wllWallFlags[0]; + } } } diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp index 15f3c80b22d..6feac6bd77f 100644 --- a/engines/kyra/script_eob.cpp +++ b/engines/kyra/script_eob.cpp @@ -638,13 +638,13 @@ int EobInfProcessor::oeob_calcAndInflictCharacterDamage(int8 *data) { int useStrModifierOrBase = *pos++; int flg = (charIndex == -1) ? 4 : 0; - int a = 5; - int damageType = 1; + int savingThrowType = 5; + int savingThrowEffect = 1; if (_vm->game() == GI_EOB2) { flg = *pos++; - a = *pos++; - damageType = *pos++; + savingThrowType = *pos++; + savingThrowEffect = *pos++; } else if (!itemOrPips) { useStrModifierOrBase = times; times = 0; @@ -652,9 +652,9 @@ int EobInfProcessor::oeob_calcAndInflictCharacterDamage(int8 *data) { if (charIndex == -1) { for (int i = 0; i < 6; i++) - _vm->calcAndInflictCharacterDamage(i, times, itemOrPips, useStrModifierOrBase, flg, a, damageType); + _vm->calcAndInflictCharacterDamage(i, times, itemOrPips, useStrModifierOrBase, flg, savingThrowType, savingThrowEffect); } else { - _vm->calcAndInflictCharacterDamage(charIndex, times, itemOrPips, useStrModifierOrBase, flg, a, damageType); + _vm->calcAndInflictCharacterDamage(charIndex, times, itemOrPips, useStrModifierOrBase, flg, savingThrowType, savingThrowEffect); } return pos - data; } diff --git a/engines/kyra/sequences_eob2.cpp b/engines/kyra/sequences_eob2.cpp index 395e94713cb..ea96779bb1c 100644 --- a/engines/kyra/sequences_eob2.cpp +++ b/engines/kyra/sequences_eob2.cpp @@ -239,7 +239,7 @@ void DarkMoonEngine::seq_playIntro() { sq.loadScene(1, 2); sq.waitForSongNotifier(4); - //intro scroll + // intro scroll if (!skipFlag() && !shouldQuit()) { for (int i = 0; i < 280; i += 3) { uint32 endtime = _system->getMillis() + _tickLength; @@ -978,7 +978,7 @@ void DarkmoonSequenceHelper::loadScene(int index, int pageNum) { } if (!s) - error("DarkmoonSequenceHelper::loadScene(): Sequence CPS file loading failed."); + error("DarkmoonSequenceHelper::loadScene(): CPS file loading failure in scene %d", index); if (_mode == kFinale) s->read(_palettes[0]->getData(), 768); @@ -1026,7 +1026,7 @@ void DarkmoonSequenceHelper::runSequence(int index, int del) { if (s->pal) setPaletteWithoutTextColor(palIndex); delay(s->delay); - if (_mode == DarkmoonSequenceHelper::kIntro && s->pal) + if (_mode == kIntro && s->pal) setPaletteWithoutTextColor(0); break; @@ -1035,7 +1035,7 @@ void DarkmoonSequenceHelper::runSequence(int index, int del) { shapeW = _shapes[s->obj][2]; shapeH = _shapes[s->obj][3]; - if (_mode == DarkmoonSequenceHelper::kFinale) { + if (_mode == kFinale) { _screen->setScreenDim(18); x -= (_screen->_curDim->sx << 3); y -= _screen->_curDim->sy; @@ -1045,7 +1045,7 @@ void DarkmoonSequenceHelper::runSequence(int index, int del) { x2 = x; } - _screen->drawShape(0, _shapes[s->obj], x, y, _mode == DarkmoonSequenceHelper::kIntro ? 0 : 18); + _screen->drawShape(0, _shapes[s->obj], x, y, _mode == kIntro ? 0 : 18); if (s->pal) setPaletteWithoutTextColor(palIndex); @@ -1054,7 +1054,7 @@ void DarkmoonSequenceHelper::runSequence(int index, int del) { delay(s->delay); - if (_mode == DarkmoonSequenceHelper::kIntro) { + if (_mode == kIntro) { if (s->pal) setPaletteWithoutTextColor(0); _screen->copyRegion(x - 8, y - 8, x, y, (shapeW + 1) << 3, shapeH, 2, 0, Screen::CR_NO_P_CHECK); @@ -1076,14 +1076,14 @@ void DarkmoonSequenceHelper::runSequence(int index, int del) { delay(s->delay); - if (_mode == DarkmoonSequenceHelper::kIntro && s->pal) + if (_mode == kIntro && s->pal) setPaletteWithoutTextColor(0); break; case 3: case 4: // fade shape in or out or restore background - if (_mode == DarkmoonSequenceHelper::kFinale) + if (_mode == kFinale) break; _screen->setShapeFadeMode(0, true); @@ -1109,10 +1109,10 @@ void DarkmoonSequenceHelper::runSequence(int index, int del) { case 5: // copy region - if (_mode == DarkmoonSequenceHelper::kFinale && s->pal) + if (_mode == kFinale && s->pal) setPaletteWithoutTextColor(palIndex); - _screen->copyRegion(s->x2 << 3, s->y2, s->x1, s->y1, s->w << 3, s->h, (s->obj && _mode == DarkmoonSequenceHelper::kFinale) ? 6 : 2, 0, Screen::CR_NO_P_CHECK); + _screen->copyRegion(s->x2 << 3, s->y2, s->x1, s->y1, s->w << 3, s->h, (s->obj && _mode == kFinale) ? 6 : 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); delay(s->delay); break; diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index e4001b24d72..caf4a748da4 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -587,7 +587,24 @@ void EobCoreEngine::drawMonsters(int index) { } void EobCoreEngine::drawWallOfForce(int index) { + int d = _dscDimMap[index]; + assert(d < 3); + int dH = _wallOfForceDsNumH[d]; + int dW = _wallOfForceDsNumW[d]; + int y = _wallOfForceDsY[d]; + int shpId = _wallOfForceShpId[d] + _teleporterPulse; + int h = _wallOfForceShapes[shpId][1]; + int w = _wallOfForceShapes[shpId][2] << 3; + for (int i = 0; i < dH; i++) { + int x = _wallOfForceDsX[index]; + for (int ii = 0; ii < dW; ii++) { + drawBlockObject(0, 2, _wallOfForceShapes[shpId], x, y, 5); + x += w; + } + y += h; + shpId ^= 1; + } } void EobCoreEngine::drawFlyingObjects(int index) { diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index 5995f8a5cd7..069bf1337d1 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -1280,6 +1280,12 @@ void DarkMoonEngine::initStaticResource() { _dranFoolsStrings = _staticres->loadStrings(kEob2DranFoolsStrings, temp); _hornStrings = _staticres->loadStrings(kEob2HornStrings, temp); _hornSounds = _staticres->loadRawData(kEob2HornSounds, temp); + + _wallOfForceDsX = (const int16*)_staticres->loadRawDataBe16(kEob2WallOfForceDsX, temp); + _wallOfForceDsY = _staticres->loadRawData(kEob2WallOfForceDsY, temp); + _wallOfForceDsNumW = _staticres->loadRawData(kEob2WallOfForceNumW, temp); + _wallOfForceDsNumH = _staticres->loadRawData(kEob2WallOfForceNumH, temp); + _wallOfForceShpId = _staticres->loadRawData(kEob2WallOfForceShpId, temp); } void DarkMoonEngine::initSpells() { diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp index 20a05f9ee6b..61fa554193b 100644 --- a/engines/kyra/timer_eob.cpp +++ b/engines/kyra/timer_eob.cpp @@ -371,7 +371,7 @@ void EobCoreEngine::timerUpdateTeleporters(int timerNum) { _teleporterPulse ^= 1; for (int i = 0; i < 18; i++) { uint8 w = _visibleBlocks[i]->walls[_sceneDrawVarDown]; - if ((_flags.gameID == GI_EOB1 && w == 52) || (_flags.gameID == GI_EOB2 && (w == 44 || w == 74))) { + if ((w == _teleporterWallId) || (_flags.gameID == GI_EOB2 && w == 74)) { _sceneUpdateRequired = true; return; }