Common::Error EoBCoreEngine::loadGameState(int slot) { // Special slot id -1 for EOB1 party transfer const char *fileName = (slot == -1) ? _savegameFilename.c_str() : getSavegameFilename(slot); SaveHeader header; Common::InSaveFile *saveFile = openSaveForReading(fileName, header, (slot != -1)); if (!saveFile) return Common::Error(Common::kReadingFailed); Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES); _loading = true; if (slot != -1) _screen->fadeToBlack(10); for (int i = 0; i < 6; i++) { EoBCharacter *c = &_characters[i]; c->id = in.readByte(); c->flags = in.readByte(); in.read(c->name, 11); c->strengthCur = in.readSByte(); c->strengthMax = in.readSByte(); c->strengthExtCur = in.readSByte(); c->strengthExtMax = in.readSByte(); c->intelligenceCur = in.readSByte(); c->intelligenceMax = in.readSByte(); c->wisdomCur = in.readSByte(); c->wisdomMax = in.readSByte(); c->dexterityCur = in.readSByte(); c->dexterityMax = in.readSByte(); c->constitutionCur = in.readSByte(); c->constitutionMax = in.readSByte(); c->charismaCur = in.readSByte(); c->charismaMax = in.readSByte(); c->hitPointsCur = in.readSint16BE(); c->hitPointsMax = in.readSint16BE(); c->armorClass = in.readSByte(); c->disabledSlots = in.readByte(); c->raceSex = in.readByte(); c->cClass = in.readByte(); c->alignment = in.readByte(); c->portrait = in.readSByte(); if (slot == -1 && c->portrait < 0) c->portrait = -c->portrait + 43; c->food = in.readByte(); in.read(c->level, 3); for (int ii = 0; ii < 3; ii++) c->experience[ii] = in.readUint32BE(); delete[] c->faceShape; c->faceShape = 0; in.read(c->mageSpells, 80); in.read(c->clericSpells, 80); c->mageSpellsAvailableFlags = in.readUint32BE(); for (int ii = 0; ii < 27; ii++) c->inventory[ii] = in.readSint16BE(); uint32 ct = _system->getMillis(); for (int ii = 0; ii < 10; ii++) { c->timers[ii] = in.readUint32BE(); if (c->timers[ii]) c->timers[ii] += ct; } in.read(c->events, 10); in.read(c->effectsRemainder, 4); c->effectFlags = in.readUint32BE(); c->damageTaken = in.readByte(); in.read(c->slotStatus, 5); } setupCharacterTimers(); _screen->loadShapeSetBitmap("CHARGENA", 3, 3); for (int i = 0; i < 6; i++) { EoBCharacter *c = &_characters[i]; if (!c->flags || c->portrait < 0) continue; c->faceShape = _screen->encodeShape((c->portrait % 10) << 2, (c->portrait / 10) << 5, 4, 32, true); } _screen->loadShapeSetBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3); for (int i = 0; i < 6; i++) { EoBCharacter *c = &_characters[i]; if (!c->flags || c->portrait >= 0) continue; c->faceShape = _screen->encodeShape((-(c->portrait + 1)) << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true); } _screen->_curPage = 0; if (slot == -1) { // Skip all settings which aren't necessary for party transfer. // Jump directly to the items list. in.skip(108); } else { _currentLevel = in.readByte(); _currentSub = in.readSByte(); _currentBlock = in.readUint16BE(); _currentDirection = in.readUint16BE(); _itemInHand = in.readSint16BE(); _hasTempDataFlags = in.readUint32BE(); _partyEffectFlags = in.readUint32BE(); _updateFlags = in.readUint16BE(); _compassDirection = in.readUint16BE(); _currentControlMode = in.readUint16BE(); _updateCharNum = in.readUint16BE(); _openBookSpellLevel = in.readSByte(); _openBookSpellSelectedItem = in.readSByte(); _openBookSpellListOffset = in.readSByte(); _openBookChar = in.readByte(); _openBookType = in.readByte(); _openBookCharBackup = in.readByte(); _openBookTypeBackup = in.readByte(); _activeSpellCharId = in.readByte(); _activeSpellCharacterPos = in.readByte(); _activeSpell = in.readByte(); _returnAfterSpellCallback = in.readByte() ? true : false; _inf->loadState(in); } for (int i = 0; i < 600; i++) { EoBItem *t = &_items[i]; t->nameUnid = in.readByte(); t->nameId = in.readByte(); t->flags = in.readByte(); t->icon = in.readSByte(); t->type = in.readSByte(); t->pos = in.readSByte(); t->block = in.readSint16BE(); t->next = in.readSint16BE(); t->prev = in.readSint16BE(); t->level = in.readByte(); t->value = in.readSByte(); } // No more data needed for party transfer if (slot == -1) { _loading = false; return Common::kNoError; } for (int i = 51; i < 65; i++) { EoBItemType *t = &_itemTypes[i]; t->invFlags = in.readUint16BE(); t->handFlags = in.readUint16BE(); t->armorClass = in.readSByte(); t->allowedClasses = in.readSByte(); t->requiredHands = in.readSByte(); t->dmgNumDiceS = in.readSByte(); t->dmgNumPipsS = in.readSByte(); t->dmgIncS = in.readSByte(); t->dmgNumDiceL = in.readSByte(); t->dmgNumPipsL = in.readSByte(); t->dmgIncL = in.readSByte(); t->unk1 = in.readByte(); t->extraProperties = in.readUint16BE(); } for (int i = 0; i < 18; i++) { if (!(_hasTempDataFlags & (1 << i))) continue; if (_lvlTempData[i]) { delete[] _lvlTempData[i]->wallsXorData; delete[] _lvlTempData[i]->flags; releaseMonsterTempData(_lvlTempData[i]); releaseFlyingObjectTempData(_lvlTempData[i]); releaseWallOfForceTempData(_lvlTempData[i]); delete _lvlTempData[i]; } _lvlTempData[i] = new LevelTempData; 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++) l->flags[ii] = in.readByte(); for (int ii = 0; ii < 30; ii++) { EoBMonsterInPlay *m = &lm[ii]; m->type = in.readByte(); m->unit = in.readByte(); m->block = in.readUint16BE(); m->pos = in.readByte(); m->dir = in.readSByte(); m->animStep = in.readByte(); m->shpIndex = in.readByte(); m->mode = in.readSByte(); m->f_9 = in.readSByte(); m->curAttackFrame = in.readSByte(); m->spellStatusLeft = in.readSByte(); m->hitPointsMax = in.readSint16BE(); m->hitPointsCur = in.readSint16BE(); m->dest = in.readUint16BE(); m->randItem = in.readUint16BE(); m->fixedItem = in.readUint16BE(); m->flags = in.readByte(); m->idleAnimState = in.readByte(); m->curRemoteWeapon = in.readByte(); m->numRemoteAttacks = in.readByte(); m->palette = in.readSByte(); m->directionChanged = in.readByte(); m->stepsTillRemoteAttack = in.readByte(); m->sub = in.readByte(); } for (int ii = 0; ii < _numFlyingObjects; ii++) { EoBFlyingObject *m = &lf[ii]; m->enable = in.readByte(); m->objectType = in.readByte(); m->attackerId = in.readSint16BE(); m->item = in.readSint16BE(); m->curBlock = in.readUint16BE(); m->u2 = in.readUint16BE(); m->u1 = in.readByte(); m->direction = in.readByte(); m->distance = in.readByte(); m->callBackIndex = in.readSByte(); m->curPos = in.readByte(); 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(); } } loadLevel(_currentLevel, _currentSub); _sceneUpdateRequired = true; _screen->setFont(Screen::FID_6_FNT); for (int i = 0; i < 6; i++) { for (int ii = 0; ii < 10; ii++) { if (_characters[i].events[ii] == -57) spellCallback_start_trueSeeing(); } } _screen->setCurPage(0); gui_drawPlayField(false); if (_currentControlMode) _screen->copyRegion(176, 0, 0, 0, 144, 168, 0, 5, Screen::CR_NO_P_CHECK); _screen->setCurPage(0); gui_drawAllCharPortraitsWithStats(); drawScene(1); if (_updateFlags) { _updateFlags = 0; useMagicBookOrSymbol(_openBookChar, _openBookType); } _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); gui_toggleButtons(); setHandItem(_itemInHand); while (!_screen->isMouseVisible()) _screen->showMouse(); _loading = false; _screen->fadeFromBlack(20); removeInputTop(); return Common::kNoError; }
void EoBCoreEngine::startSpell(int spell) { EoBSpell *s = &_spells[spell]; EoBCharacter *c = &_characters[_activeSpellCharId]; snd_playSoundEffect(s->sound); if (s->flags & 0xA0) sparkEffectDefensive(_activeSpellCharId); else if (s->flags & 0x40) sparkEffectDefensive(-1); else if (s->flags & 0x1000) sparkEffectOffensive(); if (s->flags & 0x20) { _txt->printMessage(c->name); _txt->printMessage(_flags.gameID == GI_EOB1 ? _magicStrings3[1] : _magicStrings1[5]); } if ((s->flags & 0x30) && (s->effectFlags & c->effectFlags)) { if (_flags.gameID == GI_EOB2) printWarning(Common::String::format(_magicStrings7[0], c->name, s->name).c_str()); } else if ((s->flags & 0x50) && (s->effectFlags & _partyEffectFlags)) { if (_flags.gameID == GI_EOB1 && s->effectFlags == 0x400) // EOB 1 only warns in case of a bless spell printWarning(_magicStrings8[1]); else printWarning(Common::String::format(_magicStrings7[1], s->name).c_str()); } else { if (s->flags & 8) setSpellEventTimer(spell, s->timingPara[0], s->timingPara[1], s->timingPara[2], s->timingPara[3]); _returnAfterSpellCallback = false; if (s->startCallback) (this->*s->startCallback)(); if (_returnAfterSpellCallback) return; if (s->flags & 1) c->effectFlags |= s->effectFlags; if (s->flags & 4) _partyEffectFlags |= s->effectFlags; if (s->flags & 0x200) { for (int i = 0; i < 6; i++) { if (!testCharacter(i, 1)) continue; if (!testCharacter(i, 2) && !(s->flags & 0x800)) continue; _characters[i].effectFlags |= s->effectFlags; } } if (s->flags & 2) recalcArmorClass(_activeSpellCharId); if (s->flags & 0x20A0) gui_drawCharPortraitWithStats(_activeSpellCharId); if (s->flags & 0x40) gui_drawAllCharPortraitsWithStats(); } if (_castScrollSlot) { gui_updateSlotAfterScrollUse(); } else { _characters[_openBookChar].disabledSlots |= 4; setCharEventTimer(_openBookChar, 72, 11, 1); gui_toggleButtons(); gui_drawSpellbook(); } if (_flags.gameID == GI_EOB2) { //_castSpellWd1 = spell; runLevelScript(_currentBlock, 0x800); //_castSpellWd1 = 0; } }