From 9140fd8e91882250e23e2e4b44bf3088f3da827a Mon Sep 17 00:00:00 2001 From: athrxx Date: Mon, 18 Jul 2011 01:22:58 +0200 Subject: KYRA: (EOB) - implement party resting --- engines/kyra/chargen.cpp | 4 +- engines/kyra/eob1.cpp | 5 + engines/kyra/eob1.h | 2 +- engines/kyra/eob2.cpp | 36 +++ engines/kyra/eob2.h | 14 ++ engines/kyra/eobcommon.cpp | 173 ++++++++++---- engines/kyra/eobcommon.h | 27 ++- engines/kyra/gui_eob.cpp | 496 ++++++++++++++++++++++++++++++++-------- engines/kyra/gui_eob.h | 5 +- engines/kyra/items_eob.cpp | 2 +- engines/kyra/magic_eob.cpp | 38 ++- engines/kyra/resource.h | 2 + engines/kyra/saveload_eob.cpp | 4 +- engines/kyra/sequences_eob2.cpp | 73 ++++++ engines/kyra/sprites_eob.cpp | 19 +- engines/kyra/staticres_eob.cpp | 3 +- engines/kyra/text_eob.cpp | 8 +- engines/kyra/timer.cpp | 20 ++ engines/kyra/timer.h | 2 + engines/kyra/timer_eob.cpp | 17 ++ 20 files changed, 780 insertions(+), 170 deletions(-) (limited to 'engines') diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp index 3147fbb850..c8040ed9de 100644 --- a/engines/kyra/chargen.cpp +++ b/engines/kyra/chargen.cpp @@ -1270,10 +1270,10 @@ void CharacterGenerator::finish() { for (int i = 0; i < 4; i++) { if (_vm->_classModifierFlags[_characters[i].cClass] & 2) - _characters[i].mageSpellsAvailabilityFlags = (_vm->game() == GI_EOB2) ? 0x81CB6 : 0x26C; + _characters[i].mageSpellsAvailableFlags = (_vm->game() == GI_EOB2) ? 0x81CB6 : 0x26C; if (_vm->_classModifierFlags[_characters[i].cClass] & 0x14 && _vm->game() == GI_EOB2) { - // Cleric: Turn Undead + // Cleric/Paladin: Add Turn Undead spell _characters[i].clericSpells[0] = 29; } } diff --git a/engines/kyra/eob1.cpp b/engines/kyra/eob1.cpp index 3992b2284e..70031bfd27 100644 --- a/engines/kyra/eob1.cpp +++ b/engines/kyra/eob1.cpp @@ -24,6 +24,7 @@ #include "kyra/eob1.h" #include "kyra/resource.h" +#include "kyra/sound.h" namespace Kyra { @@ -77,6 +78,10 @@ void EobEngine::startupNew() { EobCoreEngine::startupNew(); } +void EobEngine::startupLoad() { + _sound->loadSoundFile("ADLIB"); +} + void EobEngine::npcSequence(int npcIndex) { diff --git a/engines/kyra/eob1.h b/engines/kyra/eob1.h index 8181f3281e..8a959e9fa4 100644 --- a/engines/kyra/eob1.h +++ b/engines/kyra/eob1.h @@ -48,7 +48,7 @@ private: // Main loop void startupNew(); - void startupLoad() {} + void startupLoad(); // Intro/Outro void seq_playOpeningCredits(); diff --git a/engines/kyra/eob2.cpp b/engines/kyra/eob2.cpp index baed595e8c..8f3a10c374 100644 --- a/engines/kyra/eob2.cpp +++ b/engines/kyra/eob2.cpp @@ -271,6 +271,24 @@ void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, in initMonster(index, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem); } +bool DarkMoonEngine::killMonsterExtra(EobMonsterInPlay *m) { + if (_currentLevel == 16 && _currentSub == 1 && (_monsterProps[m->type].flags & 4)) { + if (m->type) { + _playFinale = true; + _runFlag = false; + } else { + m->hitPointsCur = 150; + m->curRemoteWeapon = 0; + m->numRemoteAttacks = 255; + m->shpIndex++; + m->type++; + seq_dranDragonTransformation(); + } + return false; + } + return true; +} + const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) { _screen->loadEobBitmap(filename, 3, 3); for (int i = 0; i < 3; i++) { @@ -319,6 +337,24 @@ void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5); } +void DarkMoonEngine::restParty_npc() { + +} + +bool DarkMoonEngine::restParty_extraAbortCondition() { + if (_currentLevel != 3) + return false; + + seq_nightmare(); + + return true; +} + +void DarkMoonEngine::checkPartyStatusExtra() { + if (checkScriptFlag(0x10)) + seq_dranFools(); +} + void DarkMoonEngine::drawLightningColumn() { int f = rollDice(1, 2, -1); int y = 0; diff --git a/engines/kyra/eob2.h b/engines/kyra/eob2.h index 22193cecf2..93a3518f35 100644 --- a/engines/kyra/eob2.h +++ b/engines/kyra/eob2.h @@ -60,6 +60,7 @@ private: // Main Menu int mainMenu(); int mainMenuLoop(); + int _menuChoiceInit; // Main loop @@ -85,6 +86,13 @@ private: static const char *_palFilesIntro[]; static const char *_palFilesFinale[]; + // Ingame sequence + void seq_nightmare(); + void seq_dranFools(); + void seq_dranDragonTransformation(); + + const char *const *_dranFoolsStrings; + // characters void npcSequence(int npcIndex); @@ -99,6 +107,7 @@ private: void generateMonsterPalettes(const char *file, int16 monsterIndex); void loadMonsterDecoration(const char *file, int16 monsterIndex); void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem); + bool killMonsterExtra(EobMonsterInPlay *m); // Level const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs); @@ -106,7 +115,12 @@ private: const uint8 *_dscDoorType5Offs; + // Rest party + void restParty_npc(); + bool restParty_extraAbortCondition(); + // misc + void checkPartyStatusExtra(); void drawLightningColumn(); int resurrectionSelectDialogue(); int charSelectDialogue(); diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index 4c8d4886fd..eebe7528b4 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -135,6 +135,7 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _spells = 0; _spellAnimBuffer = 0; _clericSpellOffset = 0; + _restPartyElapsedTime = 0; } EobCoreEngine::~EobCoreEngine() { @@ -351,6 +352,7 @@ Common::Error EobCoreEngine::go() { if (_gameToLoad != -1) { if (loadGameState(_gameToLoad).getCode() != Common::kNoError) error("Couldn't load game slot %d on startup", _gameToLoad); + startupLoad(); _gameToLoad = -1; } else { action = mainMenu(); @@ -434,7 +436,7 @@ void EobCoreEngine::runLoop() { while (!shouldQuit() && _runFlag) { //_runLoopUnk2 = _currentBlock; - updateCharacterEvents(true); + checkPartyStatus(true); checkInput(_activeButtons, true, 0); removeInputTop(); @@ -444,16 +446,18 @@ void EobCoreEngine::runLoop() { if (_sceneUpdateRequired) drawScene(1); - if (_envAudioTimer >= _system->getMillis()) + if (_envAudioTimer >= _system->getMillis() || (_flags.gameID == GI_EOB1 && (_currentLevel == 0 || _currentLevel > 3))) continue; _envAudioTimer = _system->getMillis() + (rollDice(1, 10, 3) * 18 * _tickLength); - snd_processEnvironmentalSoundEffect(rollDice(1, 2, -1) ? 27 : 28, _currentBlock + rollDice(1, 12, -1)); + snd_processEnvironmentalSoundEffect(_flags.gameID == GI_EOB1 ? 30 : (rollDice(1, 2, -1) ? 27 : 28), _currentBlock + rollDice(1, 12, -1)); updateEnvironmentalSfx(0); + //TODO + //EOB1__level_2_7__turnUndead(); } } -bool EobCoreEngine::updateCharacterEvents(bool a) { +bool EobCoreEngine::checkPartyStatus(bool handleDeath) { int numChars = 0; for (int i = 0; i < 6; i++) numChars += testCharacter(i, 13); @@ -461,21 +465,22 @@ bool EobCoreEngine::updateCharacterEvents(bool a) { if (numChars) return false; - if (!a) + if (!handleDeath) return true; - gui_drawAllCharPortraitsWithStats(); + checkPartyStatusExtra(); + + if (_gui->confirmDialogue2(14, 67, 1)) { + _screen->setFont(Screen::FID_8_FNT); + gui_updateControls(); + if (_gui->runLoadMenu(0, 0)) { + _screen->setFont(Screen::FID_6_FNT); + return true; + } + } - /// TODO - /// if (checkScriptFlag(0x10)) - /// j_dranThoseFools() - - /// TODO - - /// TODO - - + quitGame(); return false; } @@ -932,13 +937,13 @@ int EobCoreEngine::countCharactersWithSpecificItems(int16 itemType, int16 itemVa for (int i = 0; i < 6; i++) { if (!testCharacter(i, 1)) continue; - if (checkCharacterInventoryForItem(i, itemType, itemValue) != -1) + if (checkInventoryForItem(i, itemType, itemValue) != -1) res++; } return res; } -int EobCoreEngine::checkCharacterInventoryForItem(int character, int16 itemType, int16 itemValue) { +int EobCoreEngine::checkInventoryForItem(int character, int16 itemType, int16 itemValue) { for (int i = 0; i < 27; i++) { uint16 inv = _characters[character].inventory[i]; if (!inv) @@ -1275,6 +1280,118 @@ int EobCoreEngine::runDialogue(int dialogueTextId, int style, const char *button return res; } +void EobCoreEngine::restParty_displayWarning(const char *str) { + int od = _screen->curDimIndex(); + _screen->setScreenDim(7); + Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); + _screen->setCurPage(0); + + _txt->printMessage(Common::String::format("\r%s\r", str).c_str()); + + _screen->setFont(of); + _screen->setScreenDim(od); +} + +bool EobCoreEngine::restParty_updateMonsters() { + bool sfxEnabled = _sound->sfxEnabled(); + bool musicEnabled = _sound->musicEnabled(); + _sound->enableSFX(false); + _sound->enableMusic(false); + + for (int i = 0; i < 5; i++) { + _partyResting = true; + Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); + int od = _screen->curDimIndex(); + _screen->setScreenDim(7); + updateMonsters(0); + updateMonsters(1); + timerProcessFlyingObjects(0); + _screen->setScreenDim(od); + _screen->setFont(of); + _partyResting = false; + + for (int ii = 0; ii < 30; ii++) { + if (_monsters[ii].mode == 8) + continue; + if (getBlockDistance(_currentBlock, _monsters[ii].block) >= 2) + continue; + + restParty_displayWarning(_menuStringsRest4[0]); + _sound->enableSFX(sfxEnabled); + _sound->enableMusic(musicEnabled); + return true; + } + } + + _sound->enableSFX(sfxEnabled); + _sound->enableMusic(musicEnabled); + return false; +} + +int EobCoreEngine::restParty_getCharacterWithLowestHp() { + int lhp = 900; + int res = -1; + + for (int i = 0; i < 6; i++) { + if (!testCharacter(i, 3)) + continue; + if (_characters[i].hitPointsCur >= _characters[i].hitPointsMax) + continue; + if (_characters[i].hitPointsCur < lhp) { + lhp = _characters[i].hitPointsCur; + res = i; + } + } + + return res + 1; +} + +bool EobCoreEngine::restParty_checkHealSpells(int charIndex) { + static const uint8 eob1healSpells[] = { 2, 15, 20 }; + static const uint8 eob2healSpells[] = { 3, 16, 20 }; + const uint8 *spells = _flags.gameID == GI_EOB1 ? eob1healSpells : eob2healSpells; + const int8 *list = _characters[charIndex].clericSpells; + + for (int i = 0; i < 80; i++) { + int s = list[i] < 0 ? -list[i] : list[i]; + if (s == spells[0] || s == spells[1] || s == spells[2]) + return true; + } + + return false; +} + +bool EobCoreEngine::restParty_checkSpellsToLearn() { + for (int i = 0; i < 6; i++) { + if (!testCharacter(i, 0x43)) + continue; + + if ((getCharacterLevelIndex(2, _characters[i].cClass) != -1 || getCharacterLevelIndex(4, _characters[i].cClass) != -1) && (checkInventoryForItem(i, 30, -1) != -1)) { + for (int ii = 0; ii < 80; ii++) { + if (_characters[i].clericSpells[ii] < 0) + return true; + } + } + + if ((getCharacterLevelIndex(1, _characters[i].cClass) != -1) && (checkInventoryForItem(i, 29, -1) != -1)) { + for (int ii = 0; ii < 80; ii++) { + if (_characters[i].mageSpells[ii] < 0) + return true; + } + } + } + + return false; +} + +void EobCoreEngine::restParty_npc() { + +} + +bool EobCoreEngine::restParty_extraAbortCondition() { + return false; +} + void EobCoreEngine::delay(uint32 millis, bool, bool) { while (millis && !shouldQuit() && !skipFlag()) { updateInput(); @@ -1319,28 +1436,6 @@ void EobCoreEngine::displayParchment(int id) { restoreAfterDialogueSequence(); } -bool EobCoreEngine::restParty() { - if (_inf->preventRest()) { - assert(_menuStringsRest3[0]); - displayRestWarning(_menuStringsRest3[0]); - return true; - } - - return true; -} - -void EobCoreEngine::displayRestWarning(const char *str) { - int od = _screen->curDimIndex(); - _screen->setScreenDim(7); - Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); - _screen->setCurPage(0); - - _txt->printMessage(Common::String::format("\r%s\r", str).c_str()); - - _screen->setFont(of); - _screen->setScreenDim(od); -} - void EobCoreEngine::useSlotWeapon(int charIndex, int slotIndex, int item) { EobCharacter *c = &_characters[charIndex]; int tp = item ? _items[item].type : 0; diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index e6b816e291..0cf2e9dc38 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -108,7 +108,7 @@ struct EobCharacter { int8 mageSpells[80]; int8 clericSpells[80]; - uint32 mageSpellsAvailabilityFlags; + uint32 mageSpellsAvailableFlags; Item inventory[27]; uint32 timers[10]; @@ -311,7 +311,7 @@ protected: virtual void startupLoad() = 0; void runLoop(); void update() { screen()->updateScreen(); } - bool updateCharacterEvents(bool a); + bool checkPartyStatus(bool handleDeath); bool _runFlag; //int _runLoopUnk2; @@ -334,6 +334,7 @@ protected: void setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer); void deleteCharEventTimer(int charIndex, int evnt); void setupCharacterTimers(); + void manualAdvanceTimer(int sysTimer, uint32 millis); void timerProcessMonsters(int timerNum); void timerSpecialCharacterUpdate(int timerNum); @@ -349,6 +350,8 @@ protected: static const uint8 _clock2Timers[]; static const uint8 _numClock2Timers; + int32 _restPartyElapsedTime; + // Mouse void setHandItem(Item itemIndex); @@ -369,7 +372,7 @@ protected: int getCharacterLevelIndex(int type, int cClass); int countCharactersWithSpecificItems(int16 itemType, int16 itemValue); - int checkCharacterInventoryForItem(int character, int16 itemType, int16 itemValue); + int checkInventoryForItem(int character, int16 itemType, int16 itemValue); void modifyCharacterHitpoints(int character, int16 points); void neutralizePoison(int character); @@ -471,6 +474,7 @@ protected: void placeMonster(EobMonsterInPlay *m, uint16 block, int dir); virtual void replaceMonster(int b, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) = 0; void killMonster(EobMonsterInPlay *m, bool giveExperience); + virtual bool killMonsterExtra(EobMonsterInPlay *m); int countSpecificMonsters(int type); void updateAttackingMonsterFlags(); @@ -533,7 +537,7 @@ protected: const uint8 *_monsterProximityTable; const uint8 *_findBlockMonstersTable; const char *const *_monsterDustStrings; - + const uint8 *_monsterDistAttType10; const uint8 *_monsterDistAttSfx10; const uint8 *_monsterDistAttType17; @@ -766,12 +770,19 @@ protected: const char *const *_cancelStrings; const char *const *_abortStrings; + // Rest party + void restParty_displayWarning(const char *str); + bool restParty_updateMonsters(); + int restParty_getCharacterWithLowestHp(); + bool restParty_checkHealSpells(int charIndex); + bool restParty_checkSpellsToLearn(); + virtual void restParty_npc(); + virtual bool restParty_extraAbortCondition(); + // misc void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); void displayParchment(int id); - - bool restParty(); - void displayRestWarning(const char *str); + virtual void checkPartyStatusExtra() {} virtual void drawLightningColumn() {} virtual int resurrectionSelectDialogue() { return -1; } @@ -843,7 +854,7 @@ protected: void sparkEffectDefensive(int charIndex); void sparkEffectOffensive(); void setSpellEventTimer(int spell, int timerBaseFactor, int timerLength, int timerLevelFactor, int updateExistingTimer); - void cleanupCharacterSpellList(int charIndex); + void sortCharacterSpellList(int charIndex); bool magicObjectHit(EobFlyingObject *fo, int dcTimes, int dcPips, int dcOffs, int level); diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp index 936567b5bf..3a71642f9b 100644 --- a/engines/kyra/gui_eob.cpp +++ b/engines/kyra/gui_eob.cpp @@ -24,6 +24,7 @@ #include "kyra/eobcommon.h" #include "kyra/gui_eob.h" +#include "kyra/script_eob.h" #include "kyra/text_eob.h" #include "kyra/timer.h" #include "kyra/util.h" @@ -508,7 +509,7 @@ void EobCoreEngine::gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 } void EobCoreEngine::gui_drawCharPortraitStatusFrame(int index) { - uint8 boxColor = ((_partyEffectFlags & 0x20000) | (_partyEffectFlags & 0xffff)) ? 4 : 6; + uint8 redGreenColor = (_partyEffectFlags & 0x20000) ? 4 : 6; static const uint8 xCoords[] = { 8, 80 }; static const uint8 yCoords[] = { 2, 54, 106 }; @@ -520,18 +521,16 @@ void EobCoreEngine::gui_drawCharPortraitStatusFrame(int index) { EobCharacter *c = &_characters[index]; - int v8 = (_flags.gameID == GI_EOB2 && ((c->effectFlags & 0x4818) || c->effectsRemainder[0] || c->effectsRemainder[1] || ((_partyEffectFlags & 0x20000) | (_partyEffectFlags & 0xffff)))) || - (_flags.gameID == GI_EOB1 && ((c->effectFlags & 0x302) || c->effectsRemainder[0] || c->effectsRemainder[1])) ? 1 : 0; - int vA = (_flags.gameID == GI_EOB2 && ((((c->effectFlags & 0x3000) | (c->effectFlags & 0x10000)) || (_partyEffectFlags & 0x8420)))) || - (_flags.gameID == GI_EOB1 && ((c->effectFlags & 0x4c8) || _partyEffectFlags & 300000))? 1 : 0; + bool redGreen = ((c->effectFlags & 0x4818) || (_partyEffectFlags & 0x20000) || c->effectsRemainder[0] || c->effectsRemainder[1]) ? true : false; + bool yellow = ((c->effectFlags & 0x13000) || (_partyEffectFlags & 0x8420) || c->effectsRemainder[0] || c->effectsRemainder[1]) ? true : false; - if (v8 || vA) { - if (v8 && !vA) { - _screen->drawBox(x, y, x + 63, y + 49, boxColor); + if (redGreen || yellow) { + if (redGreen && !yellow) { + _screen->drawBox(x, y, x + 63, y + 49, redGreenColor); return; } - if (vA && !v8) { + if (yellow && !redGreen) { _screen->drawBox(x, y, x + 63, y + 49, 5); return; } @@ -541,11 +540,11 @@ void EobCoreEngine::gui_drawCharPortraitStatusFrame(int index) { for (int i = 0; i < 64; i += 16) { x = iX + i; - if (v8) { - _screen->drawClippedLine(x, y, x + 7, y, boxColor); - _screen->drawClippedLine(x + 8, y + 49, x + 15, y + 49, boxColor); + if (redGreen) { + _screen->drawClippedLine(x, y, x + 7, y, redGreenColor); + _screen->drawClippedLine(x + 8, y + 49, x + 15, y + 49, redGreenColor); } - if (vA) { + if (yellow) { _screen->drawClippedLine(x + 8, y, x + 15, y, 5); _screen->drawClippedLine(x, y + 49, x + 7, y + 49, 5); } @@ -556,13 +555,13 @@ void EobCoreEngine::gui_drawCharPortraitStatusFrame(int index) { for (int i = 1; i < 48; i += 12) { y = iY + i - 1; - if (vA) { + if (yellow) { _screen->drawClippedLine(x, y + 1, x, y + 6, 5); _screen->drawClippedLine(x + 63, y + 7, x + 63, y + 12, 5); } - if (v8) { - _screen->drawClippedLine(x, y + 7, x, y + 12, boxColor); - _screen->drawClippedLine(x + 63, y + 1, x + 63, y + 6, boxColor); + if (redGreen) { + _screen->drawClippedLine(x, y + 7, x, y + 12, redGreenColor); + _screen->drawClippedLine(x + 63, y + 1, x + 63, y + 6, redGreenColor); } } @@ -859,7 +858,7 @@ int EobCoreEngine::clickedCamp(Button *button) { drawScene(0); for (int i = 0; i < 6; i++) - cleanupCharacterSpellList(i); + sortCharacterSpellList(i); _screen->setCurPage(0); const ScreenDim *dm = _screen->getScreenDim(10); @@ -867,8 +866,11 @@ int EobCoreEngine::clickedCamp(Button *button) { _screen->updateScreen(); - enableSysTimer(2); - updateCharacterEvents(true); + enableSysTimer(2); + manualAdvanceTimer(2, _restPartyElapsedTime); + _restPartyElapsedTime = 0; + + checkPartyStatus(true); return button->arg; } @@ -2174,11 +2176,12 @@ void GUI_Eob::runCampMenu() { switch (inputFlag) { case 0x8001: - if (_vm->restParty()) + if (restParty()) runLoop = false; else _needRest = false; redrawPortraits = true; + newMenu = 0; break; case 0x8002: @@ -2286,7 +2289,7 @@ void GUI_Eob::runCampMenu() { if (_charSelectRedraw || redrawPortraits) { for (int i = 0; i < 6; i++) { _vm->gui_drawCharPortraitWithStats(i); - _vm->cleanupCharacterSpellList(i); + _vm->sortCharacterSpellList(i); } } @@ -2334,6 +2337,74 @@ bool GUI_Eob::runLoadMenu(int x, int y) { return result; } +bool GUI_Eob::confirmDialogue2(int dim, int id, int deflt) { + int od = _screen->curDimIndex(); + Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); + _screen->setScreenDim(dim); + + drawTextBox(dim, id); + + int16 x[2]; + x[0] = (_screen->_curDim->sx << 3) + 8; + x[1] = (_screen->_curDim->sx + _screen->_curDim->w - 5) << 3; + int16 y = _screen->_curDim->sy + _screen->_curDim->h - 21; + int newHighlight = deflt ^ 1; + int lastHighlight = -1; + + for (int i = 0; i < 2; i++) + drawMenuButtonBox(x[i], y, 32, 14, false, false); + + for (bool runLoop = true; runLoop && !_vm->shouldQuit(); ) { + Common::Point p = _vm->getMousePos(); + if (_vm->posWithinRect(p.x, p.y, x[0], y, x[0] + 32, y + 14)) + newHighlight = 0; + else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14)) + newHighlight = 1; + + int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + _vm->removeInputTop(); + + if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) { + runLoop = false; + } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6]) { + newHighlight ^= 1; + } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_n]) { + newHighlight = 1; + runLoop = false; + } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_y]) { + newHighlight = 0; + runLoop = false; + } else if (inputFlag == 199 || inputFlag == 201) { + if (_vm->posWithinRect(p.x, p.y, x[0], y, x[0] + 32, y + 14)) { + newHighlight = 0; + runLoop = false; + } else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14)) { + newHighlight = 1; + runLoop = false; + } + } + + if (newHighlight != lastHighlight) { + for (int i = 0; i < 2; i++) + _screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (strlen(_vm->_menuYesNoStrings[i]) << 2) + 1, y + 3, i == newHighlight ? 6 : 15, 0); + _screen->updateScreen(); + lastHighlight = newHighlight; + } + } + + drawMenuButtonBox(x[newHighlight], y, 32, 14, true, true); + _screen->updateScreen(); + _vm->_system->delayMillis(80); + drawMenuButtonBox(x[newHighlight], y, 32, 14, false, true); + _screen->updateScreen(); + + _screen->copyRegion(0, _screen->_curDim->h, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK); + _screen->setFont(of); + _screen->setScreenDim(od); + + return newHighlight ? false : true; +} + void GUI_Eob::updateBoxFrameHighLight(int box) { static const uint8 colorTable[] = { 0x0F, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0x0C, 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0x00 @@ -2686,7 +2757,7 @@ void GUI_Eob::runMemorizePrayMenu(int charIndex, int spellType) { for (int i = 0; i < _numPages; i++) np[i] = _vm->_numSpellsMage[lv * _numPages + i]; - avltyFlags = c->mageSpellsAvailabilityFlags; + avltyFlags = c->mageSpellsAvailableFlags; } } @@ -2916,7 +2987,7 @@ void GUI_Eob::scribeScrollDialogue() { for (int i = 0; i < 32; i++) { for (int ii = 0; ii < 6; ii++) { - scrollInvSlot[i] = _vm->checkCharacterInventoryForItem(ii, 34, i + 1) + 1; + scrollInvSlot[i] = _vm->checkInventoryForItem(ii, 34, i + 1) + 1; if (scrollInvSlot[i] > 0) { numScrolls++; scrollCharacter[i] = ii; @@ -2936,7 +3007,7 @@ void GUI_Eob::scribeScrollDialogue() { if (!scrollInvSlot[i]) continue; - if (c->mageSpellsAvailabilityFlags & (1 << i)) + if (c->mageSpellsAvailableFlags & (1 << i)) scrollInvSlot[i] = 0; else menuItems[s++] = i + 1; @@ -3005,7 +3076,7 @@ void GUI_Eob::scribeScrollDialogue() { if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5]) { int t = menuItems[newHighLight] - 1; Item scItem = _vm->_characters[scrollCharacter[t]].inventory[scrollInvSlot[t] - 1]; - c->mageSpellsAvailabilityFlags |= (1 << t); + c->mageSpellsAvailableFlags |= (1 << t); _vm->_characters[scrollCharacter[t]].inventory[scrollInvSlot[t] - 1] = 0; _vm->gui_drawCharPortraitWithStats(_vm->_characters[scrollCharacter[t]].id); scrollInvSlot[t] = 0; @@ -3030,6 +3101,284 @@ void GUI_Eob::scribeScrollDialogue() { delete[] scrollInvSlot; } +bool GUI_Eob::restParty() { + static const int8 eob1healSpells[] = { 2, 15, 20, 24 }; + static const int8 eob2healSpells[] = { 3, 16, 20, 28 }; + const int8 *spells = _vm->game() == GI_EOB1 ? eob1healSpells : eob2healSpells; + + uint8 crs[6]; + memset(crs, 0, 6); + int hours = 0; + + if (_vm->_inf->preventRest()) { + assert(_vm->_menuStringsRest3[0]); + _vm->restParty_displayWarning(_vm->_menuStringsRest3[0]); + return true; + } + + if (_vm->restParty_updateMonsters()) + return true; + + if (_vm->restParty_extraAbortCondition()) + return true; + + drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false); + + int nonPoisoned = 0; + for (int i = 0; i < 6; i++) { + if (!_vm->testCharacter(i, 1)) + continue; + nonPoisoned |= _vm->testCharacter(i, 0x10); + } + + if (!nonPoisoned) { + if (!confirmDialogue(59)) + return false; + } + + int8 *list = 0; + bool useHealers = false; + bool res = false; + bool restLoop = true; + bool restContinue = false; + int injured = _vm->restParty_getCharacterWithLowestHp(); + + if (injured > 0) { + for (int i = 0; i < 6; i++) { + if (!_vm->testCharacter(i, 13)) + continue; + if (_vm->getCharacterLevelIndex(2, _vm->_characters[i].cClass) == -1 && _vm->getCharacterLevelIndex(4, _vm->_characters[i].cClass) == -1) + continue; + if (_vm->checkInventoryForItem(i, 30, -1) == -1) + continue; + if (_vm->restParty_checkHealSpells(i)) + useHealers = confirmDialogue(40); + } + } + + _screen->setClearScreenDim(7); + _screen->setFont(Screen::FID_6_FNT); + + restParty_updateRestTime(hours, true); + + for (int l = 0; !res && restLoop && !_vm->shouldQuit(); ) { + l++; + + // Regenerate spells + for (int i = 0; i < 6; i++) { + crs[i]++; + + if (!_vm->_characters[i].food) + continue; + if (!_vm->testCharacter(i, 5)) + continue; + + if (_vm->checkInventoryForItem(i, 30, -1) != -1) { + list = _vm->_characters[i].clericSpells; + + for (int ii = 0; ii < 80; ii++) { + if ((ii / 10 + 48) >= crs[i]) + break; + + if (*list >= 0) { + list++; + continue; + } + + *list *= -1; + crs[i] = 48; + _vm->_txt->printMessage(Common::String::format(_vm->_menuStringsRest2[0], _vm->_characters[i].name, _vm->_spells[_vm->_mageSpellListSize + *list].name).c_str()); + _vm->delay(80); + break; + } + } + + if (_vm->checkInventoryForItem(i, 29, -1) != -1) { + list = _vm->_characters[i].mageSpells; + + for (int ii = 0; ii < 80; ii++) { + if ((ii / 6 + 48) >= crs[i]) + break; + + if (*list >= 0) { + list++; + continue; + } + + *list *= -1; + crs[i] = 48; + _vm->_txt->printMessage(Common::String::format(_vm->_menuStringsRest2[1], _vm->_characters[i].name, _vm->_spells[*list].name).c_str()); + _vm->delay(80); + break; + } + } + } + + // Heal party members + if (useHealers) { + for (int i = 0; i < 6 && injured; i++) { + if (_vm->getCharacterLevelIndex(2, _vm->_characters[i].cClass) == -1 && _vm->getCharacterLevelIndex(4, _vm->_characters[i].cClass) == -1) + continue; + if (_vm->checkInventoryForItem(i, 30, -1) == -1) + continue; + + list = 0; + if (crs[i] >= 48) { + for (int ii = 0; !list && ii < 3; ii++) + list = (int8*)memchr(_vm->_characters[i].clericSpells, -spells[ii], 80); + } + + if (list) + break; + + list = _vm->_characters[i].clericSpells; + for (int ii = 0; ii < 80 && injured; ii++) { + int healHp = 0; + if (*list == spells[0]) + healHp = _vm->rollDice(1, 8, 0); + else if (*list == spells[1]) + healHp = _vm->rollDice(2, 8, 1); + else if (*list == spells[2]) + healHp = _vm->rollDice(3, 8, 3); + + if (!healHp) { + list++; + continue; + } + + *list *= -1; + list++; + + crs[i] = 0; + injured--; + + _vm->_txt->printMessage(Common::String::format(_vm->_menuStringsRest2[2], _vm->_characters[i].name, _vm->_characters[injured].name).c_str()); + _vm->delay(80); + + _vm->_characters[injured].hitPointsCur += healHp; + if (_vm->_characters[injured].hitPointsCur > _vm->_characters[injured].hitPointsMax) + _vm->_characters[injured].hitPointsCur = _vm->_characters[injured].hitPointsMax; + + _vm->gui_drawCharPortraitWithStats(injured++); + } + } + } + + if (l == 6) { + l = 0; + restParty_updateRestTime(++hours, false); + _vm->_restPartyElapsedTime += (32760 * _vm->_tickLength); + + // Update poisoning + for (int i = 0; i < 6; i++) { + if (!_vm->testCharacter(i, 1)) + continue; + if (_vm->testCharacter(i, 16)) + continue; + _vm->inflictCharacterDamage(i, 10); + _vm->delayWithTicks(5); + } + + if (!(hours % 8)) { + bool starving = false; + for (int i = 0; i < 6; i++) { + // Add Lay On Hands spell + if (_vm->_characters[i].cClass == 2) { + list = (int8*)memchr(_vm->_characters[i].clericSpells, spells[3], 10); + if (list) { + *list = spells[3]; + } else { + list = (int8*)memchr(_vm->_characters[i].clericSpells, -spells[3], 10); + if (list) { + *list = spells[3]; + } else if (!memchr(_vm->_characters[i].clericSpells, spells[3], 10)) { + list = (int8*)memchr(_vm->_characters[i].clericSpells, 0, 10); + *list = spells[3]; + } + } + } + + if (!_vm->testCharacter(i, 3)) + continue; + + // Update hitpoints and food status + if (_vm->_characters[i].food) { + if (_vm->_characters[i].hitPointsCur < _vm->_characters[i].hitPointsMax) { + _vm->_characters[i].hitPointsCur++; + _screen->setFont(Screen::FID_6_FNT); + _vm->gui_drawCharPortraitWithStats(i); + } + + if (!_vm->checkInventoryForRings(i, 2)) { + if (_vm->_characters[i].food <= 5) { + _vm->_characters[i].food = 0; + starving = true; + } else { + _vm->_characters[i].food -= 5; + } + } + } else { + if ((hours % 24) || (_vm->_characters[i].hitPointsCur <= -10)) + continue; + _vm->inflictCharacterDamage(i, 1); + starving = true; + _screen->setFont(Screen::FID_6_FNT); + _vm->gui_drawCharPortraitWithStats(i); + } + } + + if (starving) { + if (!confirmDialogue(47)) { + restContinue = false; + restLoop = false; + } + restParty_updateRestTime(hours, true); + } + injured = restLoop ? _vm->restParty_getCharacterWithLowestHp() : 0; + } + } + + if (!_vm->restParty_checkSpellsToLearn() && restLoop && !restContinue && injured) { + restContinue = confirmDialogue(41); + restParty_updateRestTime(hours, true); + if (!restContinue) + restLoop = false; + } + + int in = _vm->checkInput(0, false, 0); + _vm->removeInputTop(); + if (in) + restLoop = false; + + if (restLoop) { + res = _vm->restParty_updateMonsters(); + if (!res) + res = _vm->checkPartyStatus(false); + } + + if (!_vm->restParty_checkSpellsToLearn()) { + if (!restContinue) { + if (!useHealers) + restLoop = false; + } + if (!injured) + restLoop = false; + } + } + + _vm->removeInputTop(); + _screen->setScreenDim(4); + _screen->setFont(Screen::FID_8_FNT); + + if (!injured && !res) + displayTextBox(43); + + if (res && hours > 4) + _vm->restParty_npc(); + + return res; +} + bool GUI_Eob::confirmDialogue(int id) { int od = _screen->curDimIndex(); Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); @@ -3092,74 +3441,6 @@ bool GUI_Eob::confirmDialogue(int id) { return result; } -bool GUI_Eob::confirmDialogue2(int dim, int id, int deflt) { - int od = _screen->curDimIndex(); - Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); - _screen->setScreenDim(dim); - - drawTextBox(dim, id); - - int16 x[2]; - x[0] = (_screen->_curDim->sx << 3) + 8; - x[1] = (_screen->_curDim->sx + _screen->_curDim->w - 5) << 3; - int16 y = _screen->_curDim->sy + _screen->_curDim->h - 21; - int newHighlight = deflt ^ 1; - int lastHighlight = -1; - - for (int i = 0; i < 2; i++) - drawMenuButtonBox(x[i], y, 32, 14, false, false); - - for (bool runLoop = true; runLoop && !_vm->shouldQuit(); ) { - Common::Point p = _vm->getMousePos(); - if (_vm->posWithinRect(p.x, p.y, x[0], y, x[0] + 32, y + 14)) - newHighlight = 0; - else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14)) - newHighlight = 1; - - int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; - _vm->removeInputTop(); - - if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) { - runLoop = false; - } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6]) { - newHighlight ^= 1; - } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_n]) { - newHighlight = 1; - runLoop = false; - } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_y]) { - newHighlight = 0; - runLoop = false; - } else if (inputFlag == 199 || inputFlag == 201) { - if (_vm->posWithinRect(p.x, p.y, x[0], y, x[0] + 32, y + 14)) { - newHighlight = 0; - runLoop = false; - } else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14)) { - newHighlight = 1; - runLoop = false; - } - } - - if (newHighlight != lastHighlight) { - for (int i = 0; i < 2; i++) - _screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (strlen(_vm->_menuYesNoStrings[i]) << 2) + 1, y + 3, i == newHighlight ? 6 : 15, 0); - _screen->updateScreen(); - lastHighlight = newHighlight; - } - } - - drawMenuButtonBox(x[newHighlight], y, 32, 14, true, true); - _screen->updateScreen(); - _vm->_system->delayMillis(80); - drawMenuButtonBox(x[newHighlight], y, 32, 14, false, true); - _screen->updateScreen(); - - _screen->copyRegion(0, _screen->_curDim->h, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK); - _screen->setFont(of); - _screen->setScreenDim(od); - - return newHighlight ? false : true; -} - void GUI_Eob::messageDialogue(int dim, int id, int buttonTextCol) { static const char buttonText[] = "OK"; @@ -3338,7 +3619,7 @@ int GUI_Eob::selectCharacterDialogue(int id) { result = -1; } } else { - if (_vm->checkCharacterInventoryForItem(result, 29, -1) == -1) { + if (_vm->checkInventoryForItem(result, 29, -1) == -1) { displayTextBox(25); result = -1; } @@ -3635,6 +3916,31 @@ int GUI_Eob::getHighlightSlot() { return res; } +void GUI_Eob::restParty_updateRestTime(int hours, bool init) { + Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); + int od = _screen->curDimIndex(); + _screen->setScreenDim(10); + + if (init) { + _screen->setCurPage(0); + _vm->_txt->clearCurDim(); + drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false); + _screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 0, 2, Screen::CR_NO_P_CHECK); + _screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0); + } + + _screen->setCurPage(2); + _screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, 15, _vm->_bkgColor_1); + _screen->setCurPage(0); + _screen->copyRegion(((_screen->_curDim->sx + 1) << 3) - 1, _screen->_curDim->sy + 20, ((_screen->_curDim->sx + 1) << 3) - 1, _screen->_curDim->sy + 20, 144, 8, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + _vm->delay(160); + + _screen->setScreenDim(od); + _screen->setFont(of); +} + #endif // ENABLE_EOB } // End of namespace Kyra diff --git a/engines/kyra/gui_eob.h b/engines/kyra/gui_eob.h index 234f2f6ae5..709c676517 100644 --- a/engines/kyra/gui_eob.h +++ b/engines/kyra/gui_eob.h @@ -62,6 +62,7 @@ public: void runCampMenu(); bool runLoadMenu(int x, int y); + bool confirmDialogue2(int dim, int id, int deflt); void updateBoxFrameHighLight(int box); int getTextInput(char *dest, int x, int y, int destMaxLen, int textColor1, int textColor2, int cursorColor); @@ -78,9 +79,9 @@ private: int selectSaveSlotDialogue(int x, int y, int id); void runMemorizePrayMenu(int charIndex, int spellType); void scribeScrollDialogue(); + bool restParty(); bool confirmDialogue(int id); - bool confirmDialogue2(int dim, int id, int deflt); void messageDialogue(int dim, int id, int buttonTextCol); int selectCharacterDialogue(int id); void displayTextBox(int id); @@ -100,6 +101,8 @@ private: void setupSaveMenuSlots(); int getHighlightSlot(); + void restParty_updateRestTime(int hours, bool init); + Button _scrollUpButton;//////////////////77 Button _scrollDownButton; diff --git a/engines/kyra/items_eob.cpp b/engines/kyra/items_eob.cpp index f7aed1b920..c6ec81a00e 100644 --- a/engines/kyra/items_eob.cpp +++ b/engines/kyra/items_eob.cpp @@ -221,7 +221,7 @@ void EobCoreEngine::deletePartyItem(Item itemType, int16 itemValue) { continue; EobCharacter *c = &_characters[i]; - int slot = checkCharacterInventoryForItem(i, itemType, itemValue); + int slot = checkInventoryForItem(i, itemType, itemValue); if (slot == -1) continue; diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index 7a9750fb69..fe770d465e 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -235,7 +235,7 @@ void EobCoreEngine::removeCharacterEffect(int spell, int charIndex, int showWarn if (showWarning) { if (s->flags & 0x20A0) gui_drawCharPortraitWithStats(charIndex); - else if (s->flags & 0x20A0) + else if (s->flags & 0x40) gui_drawAllCharPortraitsWithStats(); } } @@ -416,8 +416,40 @@ void EobCoreEngine::setSpellEventTimer(int spell, int timerBaseFactor, int timer setCharEventTimer(_activeSpellCaster, countdown, -spell, updateExistingTimer); } -void EobCoreEngine::cleanupCharacterSpellList(int charIndex) { +void EobCoreEngine::sortCharacterSpellList(int charIndex) { + int8 *list = _characters[charIndex].mageSpells; + for (int i = 0; i < 16; ) { + bool p = false; + for (int ii = 0; ii < 9; ii++) { + int8 *pos = &list[ii]; + + int s1 = pos[0]; + int s2 = pos[1]; + + if (s1 == 0) + s1 = 80; + else if (s1 < 0) + s1 = s1 * -1 + 40; + + if (s2 == 0) + s2 = 80; + else if (s2 < 0) + s2 = s2 * -1 + 40; + + if (s1 > s2) { + SWAP(pos[0], pos[1]); + p = true; + } + } + + if (p) + continue; + + list += 10; + if (++i == 8) + list = _characters[charIndex].clericSpells; + } } bool EobCoreEngine::magicObjectHit(EobFlyingObject *fo, int dcTimes, int dcPips, int dcOffs, int level) { @@ -685,7 +717,7 @@ void EobCoreEngine::spellCallback_start_createFood() { for (int i = 0; i < 6; i++) { if (!testCharacter(i, 3)) continue; - _characters[_activeSpellCaster].food = 100; + _characters[i].food = 100; } } diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 599539c2d2..889865b8ea 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -546,6 +546,8 @@ enum KyraResources { kEob2Npc2Strings, kEob2MonsterDustStrings, + kEob2DranFoolsStrings, + kLolIngamePakFiles, kLolCharacterDefs, kLolIngameSfxFiles, diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp index a5b2a69c09..cde900bc12 100644 --- a/engines/kyra/saveload_eob.cpp +++ b/engines/kyra/saveload_eob.cpp @@ -185,7 +185,7 @@ Common::Error EobCoreEngine::loadGameState(int slot) { c->faceShape = 0; in.read(c->mageSpells, 80); in.read(c->clericSpells, 80); - c->mageSpellsAvailabilityFlags = in.readUint32BE(); + c->mageSpellsAvailableFlags = in.readUint32BE(); for (int ii = 0; ii < 27; ii++) c->inventory[ii] = in.readSint16BE(); uint32 ct = _system->getMillis(); @@ -427,7 +427,7 @@ Common::Error EobCoreEngine::saveGameStateIntern(int slot, const char *saveName, out->writeUint32BE(c->experience[ii]); out->write(c->mageSpells, 80); out->write(c->clericSpells, 80); - out->writeUint32BE(c->mageSpellsAvailabilityFlags); + out->writeUint32BE(c->mageSpellsAvailableFlags); for (int ii = 0; ii < 27; ii++) out->writeSint16BE(c->inventory[ii]); uint32 ct = _system->getMillis(); diff --git a/engines/kyra/sequences_eob2.cpp b/engines/kyra/sequences_eob2.cpp index 1cc4585e1c..8ff5581b9d 100644 --- a/engines/kyra/sequences_eob2.cpp +++ b/engines/kyra/sequences_eob2.cpp @@ -1271,6 +1271,79 @@ void DarkmoonSequenceHelper::waitForSongNotifier(int index, bool introUpdateAnim } } +void DarkMoonEngine::seq_nightmare() { + Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); + _screen->copyRegion(0, 0, 0, 120, 176, 24, 14, 2, Screen::CR_NO_P_CHECK); + + initDialogueSequence(); + gui_drawDialogueBox(); + + _txt->printDialogueText(99, 0); + snd_playSoundEffect(54); + + static const int8 dreamSteps[] = { 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 3, 2, 1, 0, -1 }; + static const uint8 seqX[] = { 0, 20, 0, 20 }; + static const uint8 seqY[] = { 0, 0, 96, 96 }; + static const uint8 seqDelay[] = { 12, 7, 7, 12 }; + + for (const int8 *i = dreamSteps; *i != -1; ++i) { + drawSequenceBitmap("DREAM", 0, seqX[*i], seqY[*i], 0); + delay(seqDelay[*i] * _tickLength); + } + + _txt->printDialogueText(20, _okStrings[0]); + + restoreAfterDialogueSequence(); + + _screen->setFont(of); +} + +void DarkMoonEngine::seq_dranFools() { + Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); + + initDialogueSequence(); + gui_drawDialogueBox(); + + static const char file[] = "KHELDRAN"; + _txt->printDialogueText(_dranFoolsStrings[0]); + drawSequenceBitmap(file, 0, 0, 0, 0); + _txt->printDialogueText(20, _moreStrings[0]); + snd_playSoundEffect(56); + drawSequenceBitmap(file, 0, 20, 0, 0); + delay(10 * _tickLength); + drawSequenceBitmap(file, 0, 0, 96, 0); + delay(10 * _tickLength); + drawSequenceBitmap(file, 0, 20, 96, 0); + delay(7 * _tickLength); + _txt->printDialogueText(76, _okStrings[0]); + + restoreAfterDialogueSequence(); + + _screen->setFont(of); +} + +void DarkMoonEngine::seq_dranDragonTransformation() { + Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); + + initDialogueSequence(); + gui_drawDialogueBox(); + + static const char file[] = "DRANX"; + drawSequenceBitmap(file, 0, 0, 0, 0); + _txt->printDialogueText(120, _moreStrings[0]); + snd_playSoundEffect(56); + drawSequenceBitmap(file, 0, 20, 0, 0); + delay(7 * _tickLength); + drawSequenceBitmap(file, 0, 0, 96, 0); + delay(7 * _tickLength); + drawSequenceBitmap(file, 0, 20, 96, 0); + delay(18 * _tickLength); + + restoreAfterDialogueSequence(); + + _screen->setFont(of); +} + } // End of namespace Kyra #endif // ENABLE_EOB diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index 109d244569..8c492aa4e2 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -224,20 +224,7 @@ void EobCoreEngine::killMonster(EobMonsterInPlay *m, bool giveExperience) { if (giveExperience) increasePartyExperience(_monsterProps[m->type].experience); - if ((_flags.gameID == GI_EOB2) && (_currentLevel == 16) && (_currentSub == 1) && (_monsterProps[m->type].flags & 4)) { - if (m->type) { - _playFinale = true; - _runFlag = false; - } else { - m->hitPointsCur = 150; - m->curRemoteWeapon = 0; - m->numRemoteAttacks = 255; - m->shpIndex++; - m->type++; - //// TODO - // dranDragonTransformation(); - } - } else { + if (killMonsterExtra(m)) { placeMonster(m, 0, -1); if ((_flags.gameID == GI_EOB1) && (m->type == 21)) { @@ -250,6 +237,10 @@ void EobCoreEngine::killMonster(EobMonsterInPlay *m, bool giveExperience) { } } +bool EobCoreEngine::killMonsterExtra(EobMonsterInPlay*) { + return true; +} + int EobCoreEngine::countSpecificMonsters(int type) { int res = 0; for (int i = 0; i < 30; i++) { diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index efc5b854b8..19789bbb3c 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -157,7 +157,7 @@ bool StaticResource::loadEobNpcData(Common::SeekableReadStream &stream, void *&p s->experience[0] = stream.readUint32BE(); s->experience[1] = stream.readUint32BE(); s->experience[2] = stream.readUint32BE(); - s->mageSpellsAvailabilityFlags = stream.readUint32BE(); + s->mageSpellsAvailableFlags = stream.readUint32BE(); for (int ii = 0; ii < 27; ii++) s->inventory[i] = stream.readUint16BE(); } @@ -1184,6 +1184,7 @@ void DarkMoonEngine::initStaticResource() { _npc1Strings = _staticres->loadStrings(kEob2Npc1Strings, temp); _npc2Strings = _staticres->loadStrings(kEob2Npc2Strings, temp); _monsterDustStrings = _staticres->loadStrings(kEob2MonsterDustStrings, temp); + _dranFoolsStrings = _staticres->loadStrings(kEob2DranFoolsStrings, temp); } void DarkMoonEngine::initSpells() { diff --git a/engines/kyra/text_eob.cpp b/engines/kyra/text_eob.cpp index 0d9bf9dffa..c350666226 100644 --- a/engines/kyra/text_eob.cpp +++ b/engines/kyra/text_eob.cpp @@ -445,9 +445,11 @@ void TextDisplayer_Eob::printDialogueText(int stringId, const char *pageBreakStr displayText(_dialogueBuffer); if (pageBreakString) { - strcpy(_pageBreakString, pageBreakString); - displayWaitButton(); - resetPageBreakString(); + if (pageBreakString[0]) { + strcpy(_pageBreakString, pageBreakString); + displayWaitButton(); + resetPageBreakString(); + } } } diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp index 2ab2b621f3..4722966cad 100644 --- a/engines/kyra/timer.cpp +++ b/engines/kyra/timer.cpp @@ -129,6 +129,26 @@ void TimerManager::update() { } } +void TimerManager::manualAdvance(uint32 millis) { + uint32 curTime = _system->getMillis(); + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + if (pos->enabled == 1 && pos->countdown >= 0) { + pos->nextRun -= curTime; + while (pos->nextRun <= millis) { + if (pos->func && pos->func->isValid()) + (*pos->func)(pos->id); + + pos->lastUpdate = curTime; + pos->nextRun = pos->countdown * _vm->tickLength(); + millis -= pos->nextRun; + } + pos->nextRun += curTime; + _nextRun = MIN(_nextRun, pos->nextRun); + } + } + +} + void TimerManager::resync() { const uint32 curTime = _isPaused ? _pauseStart : _system->getMillis(); diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h index 205be5957d..5e53d615d3 100644 --- a/engines/kyra/timer.h +++ b/engines/kyra/timer.h @@ -61,6 +61,8 @@ public: void update(); + void manualAdvance(uint32 millis); + void resetNextRun(); void setCountdown(uint8 id, int32 countdown); diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp index f6e8b63dc1..00dc758a27 100644 --- a/engines/kyra/timer_eob.cpp +++ b/engines/kyra/timer_eob.cpp @@ -193,6 +193,23 @@ void EobCoreEngine::setupCharacterTimers() { } } +void EobCoreEngine::manualAdvanceTimer(int sysTimer, uint32 millis) { + if (sysTimer != 2) + return; + + uint32 ct = _system->getMillis(); + for (int i = 0; i < 6; i++) { + for (int ii = 0; ii < 10; ii++) { + if (_characters[i].timers[ii]) { + uint32 chrt = _characters[i].timers[ii] - ct; + _characters[i].timers[ii] = chrt > millis ? chrt - millis : 1; + } + } + } + + _timer->manualAdvance(millis); +} + void EobCoreEngine::timerProcessCharacterExchange(int timerNum) { _charExchangeSwap ^= 1; if (_charExchangeSwap) { -- cgit v1.2.3