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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 TUSrtbl8vTZa^+k9y!8J82&8MW diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index dc987c15332..c94cb16703c 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -141,6 +141,8 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _restPartyElapsedTime = 0; _allowSkip = false; + _wallsOfForce = 0; + _rrCount = 0; memset(_rrNames, 0, 10 * sizeof(const char*)); memset(_rrId, 0, 10 * sizeof(int8)); @@ -205,6 +207,7 @@ EobCoreEngine::~EobCoreEngine() { delete[] _spells; delete[] _spellAnimBuffer; + delete[] _wallsOfForce; delete _gui; _gui = 0; @@ -318,6 +321,9 @@ Common::Error EobCoreEngine::init() { _spellAnimBuffer = new uint8[4096]; memset(_spellAnimBuffer, 0, 4096); + _wallsOfForce = new WallOfForce[5]; + memset(_wallsOfForce, 0, 5 * sizeof(WallOfForce)); + memset(_doorType, 0, sizeof(_doorType)); memset(_noDoorSwitch, 0, sizeof(_noDoorSwitch)); @@ -349,7 +355,6 @@ Common::Error EobCoreEngine::go() { loadItemsAndDecorationsShapes(); _screen->setMouseCursor(0, 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; }