KYRA: (EOB) - fix some bugs

- fix monster movement
- fix character level gain
- add some static res for party transfer
This commit is contained in:
athrxx 2011-08-17 18:46:29 +02:00 committed by Johannes Schickel
parent b3c8173bd4
commit f7032c126d
20 changed files with 130 additions and 64 deletions

View File

@ -463,6 +463,8 @@ const ExtractFilename extractFilenames[] = {
// EYE OF THE BEHOLDER II
{ kEob2MainMenuStrings, kTypeStringList, true },
{ kEob2TransferConvertTable, kTypeRawData, false },
{ kEob2TransferExpTable, kLolTypeRaw32, false },
{ kEob2IntroStrings, k2TypeSfxList, true },
{ kEob2IntroCPSFiles, kTypeStringList, true },
@ -1779,6 +1781,10 @@ const char *getIdString(const int id) {
return "kEob1Npc7Strings";
case kEob2MainMenuStrings:
return "kEob2MainMenuStrings";
case kEob2TransferConvertTable:
return "kEob2TransferConvertTable";
case kEob2TransferExpTable:
return "kEob2TransferExpTable";
case kEob2IntroStrings:
return "kEob2IntroStrings";
case kEob2IntroCPSFiles:

View File

@ -463,6 +463,9 @@ enum kExtractID {
kEob1Npc7Strings,
kEob2MainMenuStrings,
kEob2TransferConvertTable,
kEob2TransferExpTable,
kEob2IntroStrings,
kEob2IntroCPSFiles,
kEob2IntroSeqData00,

View File

@ -1485,6 +1485,8 @@ const int eob2FloppyNeed[] = {
kEobBaseFlightObjSclIndex,
kEob2MainMenuStrings,
kEob2TransferConvertTable,
kEob2TransferExpTable,
kEob2IntroStrings,
kEob2IntroCPSFiles,

View File

@ -2649,6 +2649,16 @@ const ExtractEntrySearchData kEob2MainMenuStringsProvider[] = {
EXTRACT_END_ENTRY
};
const ExtractEntrySearchData kEob2TransferConvertTableProvider[] = {
{ UNK_LANG, kPlatformUnknown, { 0x00000031, 0x000004BC, { { 0x96, 0x53, 0xA2, 0xF1, 0x26, 0xFE, 0x1B, 0x5E, 0xDF, 0x62, 0x2C, 0x8C, 0xBD, 0x62, 0x5A, 0xF9 } } } },
EXTRACT_END_ENTRY
};
const ExtractEntrySearchData kEob2TransferExpTableProvider[] = {
{ UNK_LANG, kPlatformUnknown, { 0x00000018, 0x0000076B, { { 0x91, 0x65, 0x5B, 0x8D, 0xE8, 0x5B, 0x28, 0x32, 0x4D, 0x7A, 0x57, 0x8E, 0x18, 0x5B, 0x1A, 0xE9 } } } },
EXTRACT_END_ENTRY
};
const ExtractEntrySearchData kEob2IntroStringsProvider[] = {
{ EN_ANY, kPlatformUnknown, { 0x00000321, 0x0000DBC3, { { 0x11, 0x9B, 0x54, 0xB3, 0x34, 0xF0, 0xB5, 0xE1, 0xFA, 0x6A, 0x31, 0x02, 0x59, 0x29, 0xCA, 0x94 } } } },
{ DE_DEU, kPlatformUnknown, { 0x0000038E, 0x0001119C, { { 0x92, 0x63, 0x18, 0xDD, 0x9F, 0x62, 0xF5, 0xBC, 0x3D, 0x93, 0xDC, 0x6E, 0xE5, 0xBE, 0x8C, 0x0B } } } },
@ -4078,6 +4088,9 @@ const ExtractEntry extractProviders[] = {
{ kEob1Npc7Strings, kEob1Npc7StringsProvider },
{ kEob2MainMenuStrings, kEob2MainMenuStringsProvider },
{ kEob2TransferConvertTable, kEob2TransferConvertTableProvider },
{ kEob2TransferExpTable, kEob2TransferExpTableProvider },
{ kEob2IntroStrings, kEob2IntroStringsProvider },
{ kEob2IntroCPSFiles, kEob2IntroCPSFilesProvider },
{ kEob2IntroSeqData00, kEob2IntroSeqData00Provider },

Binary file not shown.

View File

@ -108,10 +108,6 @@ private:
Screen_Eob *_screen;
};
bool EobCoreEngine::startCharacterGeneration() {
return CharacterGenerator(this, _screen).start(_characters, &_faceShapes);
}
CharacterGenerator::CharacterGenerator(EobCoreEngine *vm, Screen_Eob *screen) : _vm(vm), _screen(screen),
_characters(0), _faceShapes(0), _chargenMagicShapes(0), _chargenButtonLabels(0), _chargenMagicShapeTimer(0),
_updateBoxShapesIndex(0), _lastUpdateBoxShapesIndex(0), _magicShapesBox(6), _activeBox(0) {
@ -1445,6 +1441,15 @@ const int16 CharacterGenerator::_raceModifiers[] = {
0, 0, 0, 0, 1, -1, 0, 1, -1, 0, 0, 0, -1, 0, 0, 1, 0, 0
};
bool EobCoreEngine::startCharacterGeneration() {
return CharacterGenerator(this, _screen).start(_characters, &_faceShapes);
}
bool EobCoreEngine::transferParty() {
return false;
}
} // End of namespace Kyra
#endif // ENABLE_EOB

View File

@ -78,8 +78,8 @@ Common::Error EobEngine::init() {
_scriptTimersCount = 1;
_wllWallFlags[132] = 1;
_wllWallFlags[133] = 1;
//_wllWallFlags[132] = 1;
//_wllWallFlags[133] = 1;
return Common::kNoError;
}

View File

@ -40,14 +40,16 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa
_teleporterWallId(flags.gameID == GI_EOB1 ? 52 : 44) {
_screen = 0;
_gui = 0;
//_processingButtons=false;
//_runLoopUnk2 = 0;
//_runLoopTimerUnk = 0;
_playFinale = false;
_runFlag = true;
_configMouse = true;
_loading = false;
_envAudioTimer = 0;
_flashShapeTimer = 0;
_drawSceneTimer = 0;
_largeItemShapes = _smallItemShapes = _thrownItemShapes = _spellShapes = _firebeamShapes = _itemIconShapes =
_wallOfForceShapes = _teleporterShapes = _sparkShapes = _compassShapes = 0;
_redSplatShape = _greenSplatShape = _deadCharShape = _disabledCharGrid = _blackBoxSmallGrid =
@ -60,6 +62,9 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa
_beholderSpellList = 0;
_beholderSfx = 0;
_transferConvertTable = 0;
_transferExpTable = 0;
_faceShapes = 0;
_characters = 0;
_items = 0;
@ -297,6 +302,13 @@ Common::Error EobCoreEngine::init() {
memset(&_wllShapeMap[3], -1, 5);
memset(&_wllShapeMap[13], -1, 5);
/*int clen = _flags.gameID == GI_EOB2 ? 80 : 70;
memcpy(&_wllShapeMap[256 - clen], _wllVmpMap, clen);
memcpy(&_specialWallTypes[256 - 2 * clen], _wllVmpMap, clen);
memcpy(&_specialWallTypes[256 - clen], _wllShapeMap, clen);
memcpy(&_wllWallFlags[256 - 2 * clen], _wllShapeMap, clen);
memcpy(&_wllWallFlags[256 - clen], _specialWallTypes, clen);*/
_wllVcnOffset = 16;
_monsters = new EobMonsterInPlay[30];
@ -384,7 +396,9 @@ Common::Error EobCoreEngine::go() {
startupNew();
} else if (action == -3) {
// transfer party
repeatLoop = false;
repeatLoop = transferParty();
if (repeatLoop && !shouldQuit())
startupNew();
}
}
@ -441,15 +455,13 @@ void EobCoreEngine::runLoop() {
_envAudioTimer = _system->getMillis() + (rollDice(1, 10, 3) * 18 * _tickLength);
_flashShapeTimer = 0;
_drawSceneTimer = _system->getMillis();
//__unkB__ = 1;
_screen->setFont(Screen::FID_6_FNT);
_screen->setScreenDim(7);
//_runLoopUnk2 = _currentBlock;
_runFlag = true;
while (!shouldQuit() && _runFlag) {
//_runLoopUnk2 = _currentBlock;
checkPartyStatus(true);
checkInput(_activeButtons, true, 0);
removeInputTop();
@ -723,7 +735,7 @@ int EobCoreEngine::generateCharacterHitpointsByLevel(int charIndex, int levelInd
int EobCoreEngine::getClassAndConstHitpointsModifier(int cclass, int constitution) {
int res = _hpConstModifiers[constitution];
// This also applies to EOB1 despite being coded differently there
if (res <= 2 || (_classModifierFlags[cclass] & 0x31))
return res;
@ -1176,7 +1188,7 @@ uint32 EobCoreEngine::getRequiredExperience(int cClass, int levelIndex, int leve
void EobCoreEngine::increaseCharacterLevel(int charIndex, int levelIndex) {
_characters[charIndex].level[levelIndex]++;
int hpInc = generateCharacterHitpointsByLevel(charIndex, levelIndex);
int hpInc = generateCharacterHitpointsByLevel(charIndex, 1 << levelIndex);
_characters[charIndex].hitPointsCur += hpInc;
_characters[charIndex].hitPointsMax += hpInc;

View File

@ -317,8 +317,9 @@ protected:
bool _runFlag;
//int _runLoopUnk2;
// Create Party
// Character generation / party transfer
bool startCharacterGeneration();
bool transferParty();
uint8 **_faceShapes;
@ -329,6 +330,9 @@ protected:
static const uint8 _charClassModUnk[];
const uint8 *_classModifierFlags;
const uint8 *_transferConvertTable;
const uint32 *_transferExpTable;
// timers
void setupTimers();
@ -509,7 +513,7 @@ protected:
void updateMonsters(int unit);
void updateMonsterDest(EobMonsterInPlay *m);
void updateMonsterDest2(EobMonsterInPlay *m);
void updateMonsterAttackMode(EobMonsterInPlay *m);
void updateAllMonsterDests();
void turnFriendlyMonstersHostile();
int getNextMonsterDirection(int curBlock, int destBlock);

View File

@ -1978,8 +1978,6 @@ int GUI_Eob::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8
if (!result)
result = inputFlags;
//_vm->_processingButtons=false;
return result;
}
@ -2773,7 +2771,6 @@ int GUI_Eob::selectSaveSlotDialogue(int x, int y, int id) {
// Display highlighted slot index in the bottom left corner to avoid people getting lost with the 990 save slots
_screen->setFont(Screen::FID_6_FNT);
_screen->fillRect(_saveSlotX + 5, _saveSlotY + 135, _saveSlotX + 46, _saveSlotY + 140, _vm->_bkgColor_1);
int sli = (newHighlight == 6) ? _savegameOffset : (_savegameOffset + newHighlight);
_screen->printText(Common::String::format("%03d/989", sli).c_str(), _saveSlotX + 5, _saveSlotY + 135, _vm->_color2_1, _vm->_bkgColor_1);
_screen->setFont(Screen::FID_8_FNT);
@ -3980,6 +3977,7 @@ void GUI_Eob::releaseButtons(Button *list) {
delete list;
list = n;
}
_vm->gui_notifyButtonListChanged();
}
void GUI_Eob::setupSaveMenuSlots() {

View File

@ -1163,6 +1163,7 @@ void LoLEngine::setCharacterUpdateEvent(int charNum, int updateType, int updateD
l->characterUpdateEvents[i] = updateType;
l->characterUpdateDelay[i] = updateDelay;
_timer->setNextRun(3, _system->getMillis());
_timer->resetNextRun();
_timer->enable(3);
break;
}

View File

@ -164,14 +164,14 @@ Common::Error LolEobBaseEngine::init() {
_levelBlockProperties = new LevelBlockProperty[1025];
memset(_levelBlockProperties, 0, 1025 * sizeof(LevelBlockProperty));
_wllVmpMap = new uint8[255];
memset(_wllVmpMap, 0, 255);
_wllShapeMap = new int8[255];
memset(_wllShapeMap, 0, 255);
_specialWallTypes = new uint8[255];
memset(_specialWallTypes, 0, 255);
_wllWallFlags = new uint8[255];
memset(_wllWallFlags, 0, 255);
_wllVmpMap = new uint8[256];
memset(_wllVmpMap, 0, 256);
_wllShapeMap = new int8[256];
memset(_wllShapeMap, 0, 256);
_specialWallTypes = new uint8[256];
memset(_specialWallTypes, 0, 256);
_wllWallFlags = new uint8[256];
memset(_wllWallFlags, 0, 256);
_blockDrawingBuffer = new uint16[1320];
memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16));

View File

@ -537,6 +537,9 @@ enum KyraResources {
kEob1Npc7Strings,
kEob2MainMenuStrings,
kEob2TransferConvertTable,
kEob2TransferExpTable,
kEob2IntroStrings,
kEob2IntroCPSFiles,
kEob2IntroSeqData00,

View File

@ -1012,8 +1012,8 @@ void EobCoreEngine::drawScene(int refresh) {
}
if (_sceneDefaultUpdate) {
resetSkipFlag();
delayUntil(_drawSceneTimer);
removeInputTop();
}
if (refresh && !_partyResting)
@ -1029,7 +1029,7 @@ void EobCoreEngine::drawScene(int refresh) {
if (_sceneDefaultUpdate) {
_sceneDefaultUpdate = false;
_drawSceneTimer = _system->getMillis() /*+ 4 * _tickLength*/;
_drawSceneTimer = _system->getMillis() + 4 * _tickLength;
}
_sceneUpdateRequired = false;
@ -1141,8 +1141,8 @@ int EobCoreEngine::calcNewBlockPositionAndTestPassability(uint16 curBlock, uint1
int w = _levelBlockProperties[b].walls[direction ^ 2];
int f = _wllWallFlags[w];
if (!f)
assert((_flags.gameID == GI_EOB1 && w < 70) || (_flags.gameID == GI_EOB2 && w < 80));
//if (!f)
assert((_flags.gameID == GI_EOB1 && w < 70) || (_flags.gameID == GI_EOB2 && w < 80));
if (_flags.gameID == GI_EOB2 && w == 74 && _currentBlock == curBlock) {
for (int i = 0; i < 5; i++) {

View File

@ -151,9 +151,6 @@ void Screen_Eob::loadShapeSetBitmap(const char *file, int tempPage, int destPage
}
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::SeekableReadStream *s = _vm->resource()->createReadStream(tmp);
bool loadAlternative = false;
@ -170,15 +167,20 @@ void Screen_Eob::loadEobBitmap(const char *file, const uint8 *ditheringData, int
}
if (loadAlternative) {
tmp.setChar('X', 0);
s = _vm->resource()->createReadStream(tmp);
if (!s)
error("Screen_Eob::loadEobBitmap(): CPS file loading failed.");
s->seek(768);
loadFileDataToPage(s, destPage, 64000);
delete s;
if (_vm->game() == GI_EOB1) {
tmp.insertChar('1', tmp.size() - 4);
loadBitmap(tmp.c_str(), tempPage, destPage, 0);
} else {
tmp.setChar('X', 0);
s = _vm->resource()->createReadStream(tmp);
if (!s)
error("Screen_Eob::loadEobBitmap(): CPS file loading failed.");
s->seek(768);
loadFileDataToPage(s, destPage, 64000);
delete s;
}
}
if (copyToPage == -1) {
return;
} else if (copyToPage == 0) {

View File

@ -53,12 +53,8 @@ int LolEobBaseEngine::getBlockDistance(uint16 block1, uint16 block2) {
namespace Kyra {
void EobCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) {
Common::String s = filename;
if ((_flags.gameID == GI_EOB1) && (!scumm_stricmp(filename, "rust") || !scumm_stricmp(filename, "drider") || !scumm_stricmp(filename, "spider") || !scumm_stricmp(filename, "mantis") || !scumm_stricmp(filename, "xorn") || !scumm_stricmp(filename, "xanath")))
s += "1";
_screen->loadShapeSetBitmap(s.c_str(), 3, 3);
void EobCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) {
_screen->loadShapeSetBitmap(filename, 3, 3);
const uint16 *enc = &_encodeMonsterShpTable[encodeTableIndex << 2];
for (int i = 0; i < 6; i++, enc += 4)
@ -149,6 +145,7 @@ const uint8 *EobCoreEngine::loadActiveMonsterData(const uint8 *data, int level)
int32 del = _timer->getDelay(i);
_timer->setNextRun(i, (i & 1) ? ct + (del >> 1) * _tickLength : ct + del * _tickLength);
}
_timer->resetNextRun();
if (_hasTempDataFlags & (1 << (level - 1)))
return data + 420;
@ -470,6 +467,12 @@ void EobCoreEngine::drawBlockItems(int index) {
void EobCoreEngine::drawDoor(int index) {
int s = _visibleBlocks[index]->walls[_sceneDrawVarDown];
if (_flags.gameID == GI_EOB1 && s == 0x85)
s = 0;
assert((_flags.gameID == GI_EOB1 && s < 32) || (_flags.gameID == GI_EOB2 && s < 53));
int type = _dscDoorShpIndex[s];
int d = _dscDimMap[index];
int w = _dscShapeCoords[(index * 5 + 4) << 1];
@ -722,7 +725,7 @@ void EobCoreEngine::updateMonsters(int unit) {
updateMonsterDest(m);
if (m->mode > 0)
updateMonsterDest2(m);
updateMonsterAttackMode(m);
switch (m->mode) {
case 0:
@ -780,7 +783,7 @@ void EobCoreEngine::updateMonsterDest(EobMonsterInPlay *m) {
m->dest = _currentBlock;
}
void EobCoreEngine::updateMonsterDest2(EobMonsterInPlay *m) {
void EobCoreEngine::updateMonsterAttackMode(EobMonsterInPlay *m) {
if (!(m->flags & 1) || m->mode == 10)
return;
if (m->mode == 8) {
@ -902,7 +905,7 @@ void EobCoreEngine::updateMoveMonster(EobMonsterInPlay *m) {
EobMonsterProperty *p = &_monsterProps[m->type];
int d = getNextMonsterDirection(m->block, _currentBlock);
if ((p->capsFlags & 0x800) && !(d & 1))
if ((_flags.gameID == GI_EOB2) && (p->capsFlags & 0x800) && !(d & 1))
d >>= 1;
else
d = m->dir;
@ -1102,31 +1105,34 @@ void EobCoreEngine::walkMonster(EobMonsterInPlay *m, int destBlock) {
return;
if (m->flags & 8) {
// Interestingly, the fear spell in EOB 1 does not expire.
// I don't know whether this is intended or not.
if (_flags.gameID == GI_EOB1 ) {
d ^= 4;
} else if (--m->spellStatusLeft <= 0) {
m->spellStatusLeft = 0;
m->flags &= ~8;
} else {
d ^= 4;
} else if (m->spellStatusLeft > 0) {
if (--m->spellStatusLeft == 0)
m->flags &= ~8;
else
d ^= 4;
}
}
int d2 = (d - s) & 7;
if (b + _monsterStepTable0[_flags.gameID == GI_EOB1 ? (d >> 1) : d] == destBlock) {
if (_flags.gameID == GI_EOB1 && !(d & 1)) {
if (d2 >= 5) {
if (_flags.gameID == GI_EOB1) {
if ((b + _monsterStepTable0[d >> 1] == _currentBlock) && !(d & 1)) {
if (d2 >= 5)
s = m->dir - 1;
} else if (d2 != 0) {
else if (d2 != 0)
s = m->dir + 1;
}
walkMonsterNextStep(m, -1, s & 3);
return;
} else if (_flags.gameID == GI_EOB2) {
}
} else if (_flags.gameID == GI_EOB2) {
if (b + _monsterStepTable0[d] == destBlock) {
if (d & 1) {
int e = _monsterStepTable1[((d - 1) << 1) + m->dir];
if (e && !((_monsterProps[m->type].capsFlags & 0x200) && (rollDice(1, 4) == 4))) {
if (e && (!(_monsterProps[m->type].capsFlags & 0x200) || (rollDice(1, 4) < 4))) {
if (walkMonsterNextStep(m, b + e, -1))
return;
}

View File

@ -1241,6 +1241,9 @@ void EobEngine::initSpells() {
void DarkMoonEngine::initStaticResource() {
int temp;
_mainMenuStrings = _staticres->loadStrings(kEob2MainMenuStrings, temp);
_transferConvertTable = _staticres->loadRawData(kEob2TransferConvertTable, temp);
_transferExpTable = _staticres->loadRawDataBe32(kEob2TransferExpTable, temp);
_introStrings = _staticres->loadStrings(kEob2IntroStrings, temp);
_cpsFilesIntro = _staticres->loadStrings(kEob2IntroCPSFiles, temp);

View File

@ -149,6 +149,8 @@ void TimerManager::setCountdown(uint8 id, int32 countdown) {
uint32 curTime = _system->getMillis();
timer->lastUpdate = curTime;
timer->nextRun = curTime + countdown * _vm->tickLength();
if (timer->enabled & 2)
timer->pauseStartTime = curTime;
_nextRun = MIN(_nextRun, timer->nextRun);
}
@ -177,6 +179,8 @@ int32 TimerManager::getDelay(uint8 id) const {
void TimerManager::setNextRun(uint8 id, uint32 nextRun) {
Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
if (timer != _timers.end()) {
if (timer->enabled & 2)
timer->pauseStartTime = _system->getMillis();
timer->nextRun = nextRun;
return;
}

View File

@ -115,6 +115,7 @@ void EobCoreEngine::setupTimers() {
_timer->addTimer(5, TimerV2(timerUpdateTeleporters), 10, true);
_timer->addTimer(6, TimerV2(timerUpdateFoodStatus), 1080, true);
_timer->addTimer(7, TimerV2(timerUpdateMonsterIdleAnim), 25, true);
_timer->resetNextRun();
}
void EobCoreEngine::setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer) {
@ -132,6 +133,7 @@ void EobCoreEngine::setCharEventTimer(int charIndex, uint32 countdown, int evnt,
if (ntime < _timer->getNextRun(timerId))
_timer->setNextRun(timerId, ntime);
_timer->resetNextRun();
if (updateExistingTimer) {
bool updated = false;
@ -194,6 +196,7 @@ void EobCoreEngine::setupCharacterTimers() {
_timer->setCountdown(0x30 | i, (nextTimer - ctime) / _tickLength);
}
}
_timer->resetNextRun();
}
void EobCoreEngine::advanceTimers(uint32 millis) {

View File

@ -45,6 +45,7 @@ void LoLEngine::setupTimers() {
_timer->addTimer(9, TimerV2(timerUpdatePortraitAnimations), 10, true);
_timer->addTimer(10, TimerV2(timerUpdateLampState), 360, true);
_timer->addTimer(11, TimerV2(timerFadeMessageText), 360, false);
_timer->resetNextRun();
}
void LoLEngine::timerProcessMonsters(int timerNum) {