예제 #1
0
Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) {
	Common::String saveNameTmp;
	const char *fileName = 0;

	// Special slot id -1 to create final save for party transfer
	if (slot == -1) {
		_savegameFilename = _targetName + Common::String(".fin");
		fileName = _savegameFilename.c_str();
		saveNameTmp = _targetName + Common::String(" final");
		saveNameTmp.toUppercase();
		saveName = saveNameTmp.c_str();
	} else {
		fileName = getSavegameFilename(slot);
	}

	Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail);
	if (!out)
		return _saveFileMan->getError();

	completeDoorOperations();
	generateTempData();
	advanceTimers(_restPartyElapsedTime);
	_restPartyElapsedTime = 0;

	for (int i = 0; i < 6; i++)
		timerSpecialCharacterUpdate(0x30 + i);

	for (int i = 0; i < 6; i++) {
		EoBCharacter *c = &_characters[i];

		out->writeByte(c->id);
		out->writeByte(c->flags);
		out->write(c->name, 11);
		out->writeSByte(c->strengthCur);
		out->writeSByte(c->strengthMax);
		out->writeSByte(c->strengthExtCur);
		out->writeSByte(c->strengthExtMax);
		out->writeSByte(c->intelligenceCur);
		out->writeSByte(c->intelligenceMax);
		out->writeSByte(c->wisdomCur);
		out->writeSByte(c->wisdomMax);
		out->writeSByte(c->dexterityCur);
		out->writeSByte(c->dexterityMax);
		out->writeSByte(c->constitutionCur);
		out->writeSByte(c->constitutionMax);
		out->writeSByte(c->charismaCur);
		out->writeSByte(c->charismaMax);
		out->writeSint16BE(c->hitPointsCur);
		out->writeSint16BE(c->hitPointsMax);
		out->writeSByte(c->armorClass);
		out->writeByte(c->disabledSlots);
		out->writeByte(c->raceSex);
		out->writeByte(c->cClass);
		out->writeByte(c->alignment);
		out->writeByte(c->portrait);
		out->writeByte(c->food);
		out->write(c->level, 3);
		for (int ii = 0; ii < 3; ii++)
			out->writeUint32BE(c->experience[ii]);
		out->write(c->mageSpells, 80);
		out->write(c->clericSpells, 80);
		out->writeUint32BE(c->mageSpellsAvailableFlags);
		for (int ii = 0; ii < 27; ii++)
			out->writeSint16BE(c->inventory[ii]);
		uint32 ct = _system->getMillis();
		for (int ii = 0; ii < 10; ii++)
			out->writeUint32BE((c->timers[ii] && c->timers[ii] > ct) ? c->timers[ii] - ct : 0);

		out->write(c->events, 10);
		out->write(c->effectsRemainder, 4);
		out->writeUint32BE(c->effectFlags);
		out->writeByte(c->damageTaken);
		out->write(c->slotStatus, 5);
	}

	out->writeByte(_currentLevel);
	out->writeSByte(_currentSub);
	out->writeUint16BE(_currentBlock);
	out->writeUint16BE(_currentDirection);
	out->writeSint16BE(_itemInHand);
	out->writeUint32BE(_hasTempDataFlags);
	out->writeUint32BE(_partyEffectFlags);

	out->writeUint16BE(_updateFlags);
	out->writeUint16BE(_compassDirection);
	out->writeUint16BE(_currentControlMode);
	out->writeUint16BE(_updateCharNum);
	out->writeSByte(_openBookSpellLevel);
	out->writeSByte(_openBookSpellSelectedItem);
	out->writeSByte(_openBookSpellListOffset);
	out->writeByte(_openBookChar);
	out->writeByte(_openBookType);
	out->writeByte(_openBookCharBackup);
	out->writeByte(_openBookTypeBackup);
	out->writeByte(_activeSpellCharId);
	out->writeByte(_activeSpellCharacterPos);
	out->writeByte(_activeSpell);
	out->writeByte(_returnAfterSpellCallback ? 1 : 0);

	_inf->saveState(out);

	for (int i = 0; i < 600; i++) {
		EoBItem *t = &_items[i];
		out->writeByte(t->nameUnid);
		out->writeByte(t->nameId);
		out->writeByte(t->flags);
		out->writeSByte(t->icon);
		out->writeSByte(t->type);
		out->writeSByte(t->pos);
		out->writeSint16BE(t->block);
		out->writeSint16BE(t->next);
		out->writeSint16BE(t->prev);
		out->writeByte(t->level);
		out->writeSByte(t->value);
	}

	for (int i = 51; i < 65; i++) {
		EoBItemType *t = &_itemTypes[i];
		out->writeUint16BE(t->invFlags);
		out->writeUint16BE(t->handFlags);
		out->writeSByte(t->armorClass);
		out->writeSByte(t->allowedClasses);
		out->writeSByte(t->requiredHands);
		out->writeSByte(t->dmgNumDiceS);
		out->writeSByte(t->dmgNumPipsS);
		out->writeSByte(t->dmgIncS);
		out->writeSByte(t->dmgNumDiceL);
		out->writeSByte(t->dmgNumPipsL);
		out->writeSByte(t->dmgIncL);
		out->writeByte(t->unk1);
		out->writeUint16BE(t->extraProperties);
	}

	for (int i = 0; i < 18; i++) {
		LevelTempData *l = _lvlTempData[i];
		if (!l || !(_hasTempDataFlags & (1 << i)))
			continue;

		out->write(l->wallsXorData, 4096);
		for (int ii = 0; ii < 1024; ii++)
			out->writeByte(l->flags[ii] & 0xff);

		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];
			out->writeByte(m->type);
			out->writeByte(m->unit);
			out->writeUint16BE(m->block);
			out->writeByte(m->pos);
			out->writeSByte(m->dir);
			out->writeByte(m->animStep);
			out->writeByte(m->shpIndex);
			out->writeSByte(m->mode);
			out->writeSByte(m->f_9);
			out->writeSByte(m->curAttackFrame);
			out->writeSByte(m->spellStatusLeft);
			out->writeSint16BE(m->hitPointsMax);
			out->writeSint16BE(m->hitPointsCur);
			out->writeUint16BE(m->dest);
			out->writeUint16BE(m->randItem);
			out->writeUint16BE(m->fixedItem);
			out->writeByte(m->flags);
			out->writeByte(m->idleAnimState);
			out->writeByte(m->curRemoteWeapon);
			out->writeByte(m->numRemoteAttacks);
			out->writeSByte(m->palette);
			out->writeByte(m->directionChanged);
			out->writeByte(m->stepsTillRemoteAttack);
			out->writeByte(m->sub);
		}

		for (int ii = 0; ii < _numFlyingObjects; ii++) {
			EoBFlyingObject *m = &lf[ii];
			out->writeByte(m->enable);
			out->writeByte(m->objectType);
			out->writeSint16BE(m->attackerId);
			out->writeSint16BE(m->item);
			out->writeUint16BE(m->curBlock);
			out->writeUint16BE(m->u2);
			out->writeByte(m->u1);
			out->writeByte(m->direction);
			out->writeByte(m->distance);
			out->writeSByte(m->callBackIndex);
			out->writeByte(m->curPos);
			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();

	// check for errors
	if (out->err()) {
		warning("Can't write file '%s'. (Disk full?)", fileName);
		return Common::kUnknownError;
	} else {
		debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
	}

	delete out;

	_gui->notifyUpdateSaveSlotsList();

	return Common::kNoError;
}
예제 #2
0
Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) {
	const char *fileName = getSavegameFilename(slot);

	Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail);
	if (!out)
		return _saveFileMan->getError();

	completeDoorOperations();
	generateTempData();

	for (int i = 0; i < 4; i++) {
		LoLCharacter *c = &_characters[i];
		out->writeUint16BE(c->flags);
		out->write(c->name, 11);
		out->writeByte(c->raceClassSex);
		out->writeSint16BE(c->id);
		out->writeByte(c->curFaceFrame);
		out->writeByte(c->tempFaceFrame);
		out->writeByte(c->screamSfx);
		for (int ii = 0; ii < 8; ii++)
			out->writeUint16BE(c->itemsMight[ii]);
		for (int ii = 0; ii < 8; ii++)
			out->writeUint16BE(c->protectionAgainstItems[ii]);
		out->writeUint16BE(c->itemProtection);
		out->writeSint16BE(c->hitPointsCur);
		out->writeUint16BE(c->hitPointsMax);
		out->writeSint16BE(c->magicPointsCur);
		out->writeUint16BE(c->magicPointsMax);
		out->writeByte(c->field_41);
		out->writeUint16BE(c->damageSuffered);
		out->writeUint16BE(c->weaponHit);
		out->writeUint16BE(c->totalMightModifier);
		out->writeUint16BE(c->totalProtectionModifier);
		out->writeUint16BE(c->might);
		out->writeUint16BE(c->protection);
		out->writeSint16BE(c->nextAnimUpdateCountdown);
		for (int ii = 0; ii < 11; ii++)
			out->writeUint16BE(c->items[ii]);
		for (int ii = 0; ii < 3; ii++)
			out->writeByte(c->skillLevels[ii]);
		for (int ii = 0; ii < 3; ii++)
			out->writeSByte(c->skillModifiers[ii]);
		for (int ii = 0; ii < 3; ii++)
			out->writeUint32BE(c->experiencePts[ii]);
		for (int ii = 0; ii < 5; ii++)
			out->writeByte(c->characterUpdateEvents[ii]);
		for (int ii = 0; ii < 5; ii++)
			out->writeByte(c->characterUpdateDelay[ii]);
	}

	out->write(_wllBuffer4, 80);

	out->writeUint16BE(_currentBlock);
	out->writeUint16BE(_partyPosX);
	out->writeUint16BE(_partyPosY);
	out->writeUint16BE(_updateFlags);
	out->writeByte(_scriptDirection);
	out->writeByte(_selectedSpell);
	out->writeByte(_sceneDefaultUpdate);
	out->writeByte(_compassBroken);
	out->writeByte(_drainMagic);
	out->writeUint16BE(_currentDirection);
	out->writeUint16BE(_compassDirection);
	out->writeSByte(_selectedCharacter);
	out->writeByte(_currentLevel);
	for (int i = 0; i < 48; i++)
		out->writeSint16BE(_inventory[i]);
	out->writeSint16BE(_inventoryCurItem);
	out->writeSint16BE(_itemInHand);
	out->writeSint16BE(_lastMouseRegion);
	out->writeUint32BE(ARRAYSIZE(_flagsTable));
	out->write(_flagsTable, ARRAYSIZE(_flagsTable));
	for (int i = 0; i < 24; i++)
		out->writeUint16BE(_globalScriptVars[i]);
	out->writeByte(_brightness);
	out->writeByte(_lampOilStatus);
	out->writeSByte(_lampEffect);
	out->writeUint16BE(_credits);
	for (int i = 0; i < 8; i++)
		out->writeUint16BE(_globalScriptVars2[i]);
	out->write(_availableSpells, 7);
	out->writeUint32BE(_hasTempDataFlags);

	resetItems(0);

	for (int i = 0; i < 400; i++) {
		ItemInPlay *t = &_itemsInPlay[i];
		out->writeUint16BE(t->nextAssignedObject);
		out->writeUint16BE(t->nextDrawObject);
		out->writeByte(t->flyingHeight);
		out->writeUint16BE(t->block);
		out->writeUint16BE(t->x);
		out->writeUint16BE(t->y);
		out->writeSByte(t->level);
		out->writeUint16BE(t->itemPropertyIndex);
		out->writeUint16BE(t->shpCurFrame_flg);
		out->writeByte(t->destDirection);
		out->writeSByte(t->hitOffsX);
		out->writeSByte(t->hitOffsY);
		out->writeByte(t->currentSubFrame);
	}

	addLevelItems();

	for (int i = 0; i < 29; i++) {
		LevelTempData *l = _lvlTempData[i];
		if (!l || !(_hasTempDataFlags & (1 << i)))
			continue;

		out->write(l->wallsXorData, 4096);
		out->write(l->flags, 1024);

		for (int ii = 0; ii < 30; ii++) {
			MonsterInPlay *m = &l->monsters[ii];
			out->writeUint16BE(m->nextAssignedObject);
			out->writeUint16BE(m->nextDrawObject);
			out->writeByte(m->flyingHeight);
			out->writeUint16BE(m->block);
			out->writeUint16BE(m->x);
			out->writeUint16BE(m->y);
			out->writeSByte(m->shiftStep);
			out->writeUint16BE(m->destX);
			out->writeUint16BE(m->destY);
			out->writeByte(m->destDirection);
			out->writeSByte(m->hitOffsX);
			out->writeSByte(m->hitOffsY);
			out->writeByte(m->currentSubFrame);
			out->writeByte(m->mode);
			out->writeSByte(m->fightCurTick);
			out->writeByte(m->id);
			out->writeByte(m->direction);
			out->writeByte(m->facing);
			out->writeUint16BE(m->flags);
			out->writeUint16BE(m->damageReceived);
			out->writeSint16BE(m->hitPoints);
			out->writeByte(m->speedTick);
			out->writeByte(m->type);
			out->writeByte(m->numDistAttacks);
			out->writeByte(m->curDistWeapon);
			out->writeSByte(m->distAttackTick);
			out->writeUint16BE(m->assignedItems);
			out->write(m->equipmentShapes, 4);
		}

		for (int ii = 0; ii < 8; ii++) {
			FlyingObject *m = &l->flyingObjects[ii];
			out->writeByte(m->enable);
			out->writeByte(m->objectType);
			out->writeUint16BE(m->attackerId);
			out->writeSint16BE(m->item);
			out->writeUint16BE(m->x);
			out->writeUint16BE(m->y);
			out->writeByte(m->flyingHeight);
			out->writeByte(m->direction);
			out->writeByte(m->distance);
			out->writeSByte(m->field_D);
			out->writeByte(m->c);
			out->writeByte(m->flags);
			out->writeByte(m->wallFlags);
		}
		out->writeByte(l->monsterDifficulty);
	}

	out->finalize();

	// check for errors
	if (out->err()) {
		warning("Can't write file '%s'. (Disk full?)", fileName);
		return Common::kUnknownError;
	} else {
		debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
	}

	delete out;
	return Common::kNoError;
}