[Scummvm-cvs-logs] scummvm master -> b9198d37f7ea397c338d6c0afec05840bdf21403
sev-
sev at scummvm.org
Fri Jul 29 09:09:21 CEST 2016
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
a5fc17f0b1 WAGE: Add saveGameState() sketch
fe1f5352aa WAGE: Refine WageEngine::saveGame()
5d804f379c WAGE: Refine saveGame()
6b21b1f893 WAGE: Add World's _signature
3588351799 WAGE: Refine saveGame() once more
a4f02c7383 WAGE: Move some code in saveGame()
18476dc752 WAGE: Add loadGame() sketch
a854217bd6 WAGE: Refine loadGame()
a80547b206 WAGE: Refresh menus on load
faed7c7973 WAGE: Fix Chr::ChrArmorType unknown identifier
b9198d37f7 Merge pull request #793 from Tkachov/wage
Commit: a5fc17f0b190953b2f7d65da9b1de92e4a953fd6
https://github.com/scummvm/scummvm/commit/a5fc17f0b190953b2f7d65da9b1de92e4a953fd6
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-26T20:07:45+06:00
Commit Message:
WAGE: Add saveGameState() sketch
Copy-pasted from asvitkine/wage-engine (on java). I've managed filling
in some values, the others are 0 for now.
Changed paths:
A engines/wage/saveload.cpp
engines/wage/module.mk
engines/wage/wage.h
engines/wage/world.h
diff --git a/engines/wage/module.mk b/engines/wage/module.mk
index e150d5f..1f397b5 100644
--- a/engines/wage/module.mk
+++ b/engines/wage/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
macwindow.o \
macwindowmanager.o \
randomhat.o \
+ saveload.o \
script.o \
sound.o \
util.o \
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
new file mode 100644
index 0000000..ea3ae34
--- /dev/null
+++ b/engines/wage/saveload.cpp
@@ -0,0 +1,192 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/file.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/config-manager.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "common/translation.h"
+
+#include "gui/saveload.h"
+
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+
+#include "wage/wage.h"
+#include "wage/world.h"
+#include "wage/entities.h"
+
+#define SAVEGAME_CURRENT_VERSION 1
+
+//
+// Version 0 (ScummVM): first ScummVM version
+//
+
+namespace Wage {
+
+static const uint32 AGIflag = MKTAG('W', 'A', 'G', 'E');
+
+int WageEngine::saveGame(const Common::String &fileName, const Common::String &descriptionString) {
+ Common::OutSaveFile *out;
+ int result = 0;
+
+ debug(9, "WageEngine::saveGame(%s, %s)", fileName.c_str(), descriptionString.c_str());
+ if (!(out = _saveFileMan->openForSaving(fileName))) {
+ warning("Can't create file '%s', game not saved", fileName.c_str());
+ return -1;
+ } else {
+ debug(9, "Successfully opened %s for writing", fileName.c_str());
+ }
+
+ out->writeUint32BE(AGIflag);
+
+ // Write description of saved game, limited to WAGE_SAVEDGAME_DESCRIPTION_LEN characters + terminating NUL
+ const int WAGE_SAVEDGAME_DESCRIPTION_LEN = 127;
+ char description[WAGE_SAVEDGAME_DESCRIPTION_LEN + 1];
+
+ memset(description, 0, sizeof(description));
+ strncpy(description, descriptionString.c_str(), WAGE_SAVEDGAME_DESCRIPTION_LEN);
+ assert(WAGE_SAVEDGAME_DESCRIPTION_LEN + 1 == 128); // safety
+ out->write(description, 128);
+
+ out->writeByte(SAVEGAME_CURRENT_VERSION);
+ debug(9, "Writing save game version (%d)", SAVEGAME_CURRENT_VERSION);
+
+ // Thumbnail
+ Graphics::saveThumbnail(*out);
+
+ // Counters
+ out->writeSint16LE(_world->_scenes.size()); //numScenes
+ out->writeSint16LE(_world->_chrs.size()); //numChars
+ out->writeSint16LE(_world->_objs.size()); //numObjs
+
+ // Hex Offsets
+ out->writeSint32LE(0); //state.getChrsHexOffset()
+ out->writeSint32LE(0); //state.getObjsHexOffset()
+
+ // Unique 8-byte World Signature
+ out->writeSint32LE(0); //8-byte ints? seriously?
+
+ // More Counters
+ out->writeSint32LE(_world->_player->_context._visits); //visitNum
+ out->writeSint32LE(0); //state.getLoopNum()
+ out->writeSint32LE(_world->_player->_context._kills); //killNum
+
+ // Hex offset to player character
+ out->writeSint32LE(0); //state.getPlayerHexOffset()
+
+ // character in this scene?
+ out->writeSint32LE(0); //state.getPresCharHexOffset()
+
+ // Hex offset to current scene
+ out->writeSint32LE(0); //state.getCurSceneHexOffset()
+
+ // wearing a helmet?
+ out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::HEAD_ARMOR]> //state.getHelmetIndex()
+
+ // holding a shield?
+ out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::SHIELD_ARMOR]> //state.getShieldIndex()
+
+ // wearing chest armor?
+ out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::BODY_ARMOR]> //state.getChestArmIndex()
+
+ // wearing spiritual armor?
+ out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::MAGIC_ARMOR]> //state.getSprtArmIndex()
+
+ // TODO:
+ out->writeSint16LE(0xffff); // ???? - always FFFF
+ out->writeSint16LE(0xffff); // ???? - always FFFF
+ out->writeSint16LE(0xffff); // ???? - always FFFF
+ out->writeSint16LE(0xffff); // ???? - always FFFF
+
+ // did a character just escape?
+ out->writeSint32LE(0); //state.getRunCharHexOffset()
+
+ // players experience points
+ out->writeSint32LE(_world->_player->_context._experience);
+
+ out->writeSint16LE(0); //state.getAim()
+ out->writeSint16LE(0); //state.getOpponentAim()
+
+ // TODO:
+ out->writeSint16LE(0x0000); // always 0
+ out->writeSint16LE(0x0000); // always 0
+ out->writeSint16LE(0x0000); // always 0
+
+ // Base character stats
+ out->writeByte(_world->_player->_physicalStrength); //state.getBasePhysStr()
+ out->writeByte(_world->_player->_physicalHp); //state.getBasePhysHp()
+ out->writeByte(_world->_player->_naturalArmor); //state.getBasePhysArm()
+ out->writeByte(_world->_player->_physicalAccuracy); //state.getBasePhysAcc()
+ out->writeByte(_world->_player->_spiritualStength); //state.getBaseSprtStr()
+ out->writeByte(_world->_player->_spiritialHp); //state.getBaseSprtHp()
+ out->writeByte(_world->_player->_resistanceToMagic); //state.getBaseSprtArm()
+ out->writeByte(_world->_player->_spiritualAccuracy); //state.getBaseSprtAcc()
+ out->writeByte(_world->_player->_runningSpeed); //state.getBaseRunSpeed()
+
+ // TODO:
+ out->writeByte(0x0A); // ???? - always seems to be 0x0A
+
+ /*
+ // write user vars
+ for (short var : state.getUserVars())
+ out->->writeSint16LE(var);
+
+ // write updated info for all scenes
+ out.write(state.getSceneData());
+
+ // write updated info for all characters
+ out.write(state.getChrData());
+
+ // write updated info for all objects
+ out.write(state.getObjData());
+ */
+
+ out->finalize();
+ if (out->err()) {
+ warning("Can't write file '%s'. (Disk full?)", fileName.c_str());
+ result = -1;
+ } else
+ debug(9, "Saved game %s in file %s", descriptionString.c_str(), fileName.c_str());
+
+ delete out;
+ return result;
+}
+
+Common::String WageEngine::getSavegameFilename(int16 slotId) const {
+ Common::String saveLoadSlot = _targetName;
+ saveLoadSlot += Common::String::format(".%.3d", slotId);
+ return saveLoadSlot;
+}
+
+Common::Error WageEngine::saveGameState(int slot, const Common::String &description) {
+ Common::String saveLoadSlot = getSavegameFilename(slot);
+ if (saveGame(saveLoadSlot, description) == 0)
+ return Common::kNoError;
+ else
+ return Common::kUnknownError;
+}
+
+} // End of namespace Agi
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index eb50a2e..b1d793b 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -208,6 +208,14 @@ public:
void redrawScene();
void saveGame();
+ Common::Error saveGameState(int slot, const Common::String &description);
+
+private:
+ int saveGame(const Common::String &fileName, const Common::String &descriptionString);
+ Common::String getSavegameFilename(int16 slotId) const;
+
+public:
+
virtual GUI::Debugger *getDebugger() { return _debugger; }
private:
diff --git a/engines/wage/world.h b/engines/wage/world.h
index 468bedb..9eac072 100644
--- a/engines/wage/world.h
+++ b/engines/wage/world.h
@@ -48,10 +48,12 @@
#ifndef WAGE_WORLD_H
#define WAGE_WORLD_H
+#include "wage/entities.h"
#include "wage/macwindowmanager.h"
namespace Wage {
+class Script;
class Sound;
class World {
Commit: fe1f5352aaccd0253b22e5add14ff395e3370953
https://github.com/scummvm/scummvm/commit/fe1f5352aaccd0253b22e5add14ff395e3370953
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-27T12:36:41+06:00
Commit Message:
WAGE: Refine WageEngine::saveGame()
More values are saved now, yet some are still not found.
Changed paths:
engines/wage/saveload.cpp
engines/wage/wage.h
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index ea3ae34..7132162 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -18,6 +18,31 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
+ * MIT License:
+ *
+ * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
*/
#include "common/file.h"
@@ -48,6 +73,30 @@ namespace Wage {
static const uint32 AGIflag = MKTAG('W', 'A', 'G', 'E');
+//TODO: make sure these are calculated right: (we add flag, description, etc)
+#define VARS_INDEX 0x005E
+#define SCENES_INDEX 0x0232
+
+#define SCENE_SIZE 0x0010
+#define CHR_SIZE 0x0016
+#define OBJ_SIZE 0x0010
+
+#define GET_HEX_OFFSET(ptr, baseOffset, entrySize) ((ptr) == nullptr ? -1 : ((baseOffset) + (entrySize) * (ptr)->_index))
+#define GET_HEX_CHR_OFFSET(ptr) GET_HEX_OFFSET((ptr), chrsHexOffset, CHR_SIZE)
+#define GET_HEX_OBJ_OFFSET(ptr) GET_HEX_OFFSET((ptr), objsHexOffset, OBJ_SIZE)
+#define GET_HEX_SCENE_OFFSET(ptr) ((ptr) == nullptr ? -1 : (SCENES_INDEX + getSceneIndex(_world->_player->_currentScene) * SCENE_SIZE))
+
+int WageEngine::getSceneIndex(Scene *scene) const {
+ assert(scene);
+ Common::Array<Scene *> &orderedScenes = _world->_orderedScenes;
+ for (uint32 i = 0; i < orderedScenes.size(); ++i) {
+ if (orderedScenes[i] == scene) return i;
+ }
+
+ warning("Scene's index not found");
+ return -1;
+}
+
int WageEngine::saveGame(const Common::String &fileName, const Common::String &descriptionString) {
Common::OutSaveFile *out;
int result = 0;
@@ -83,37 +132,42 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint16LE(_world->_objs.size()); //numObjs
// Hex Offsets
- out->writeSint32LE(0); //state.getChrsHexOffset()
- out->writeSint32LE(0); //state.getObjsHexOffset()
+ int chrsHexOffset = SCENES_INDEX + _world->_scenes.size() * SCENE_SIZE; //chrs start after scenes
+ int objsHexOffset = chrsHexOffset + _world->_chrs.size() * CHR_SIZE; //objs start after chrs
+ out->writeSint32LE(chrsHexOffset);
+ out->writeSint32LE(objsHexOffset);
// Unique 8-byte World Signature
- out->writeSint32LE(0); //8-byte ints? seriously?
+ out->writeSint32LE(0); //TODO: 8-byte ints? seriously?
+
+ Chr *player = _world->_player;
+ Context &playerContext = player->_context;
// More Counters
- out->writeSint32LE(_world->_player->_context._visits); //visitNum
- out->writeSint32LE(0); //state.getLoopNum()
- out->writeSint32LE(_world->_player->_context._kills); //killNum
+ out->writeSint32LE(playerContext._visits); //visitNum
+ out->writeSint32LE(0); //TODO: state.getLoopNum()
+ out->writeSint32LE(playerContext._kills); //killNum
// Hex offset to player character
- out->writeSint32LE(0); //state.getPlayerHexOffset()
+ out->writeSint32LE(GET_HEX_CHR_OFFSET(player)); //getPlayerHexOffset() == getHexOffsetForChr(player)
// character in this scene?
- out->writeSint32LE(0); //state.getPresCharHexOffset()
+ out->writeSint32LE(GET_HEX_CHR_OFFSET(_monster)); //getPresCharHexOffset() == getHexOffsetForChr(monster)
// Hex offset to current scene
- out->writeSint32LE(0); //state.getCurSceneHexOffset()
+ out->writeSint32LE(GET_HEX_SCENE_OFFSET(player->_currentScene)); //getCurSceneHexOffset()
// wearing a helmet?
- out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::HEAD_ARMOR]> //state.getHelmetIndex()
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::HEAD_ARMOR])); //helmetIndex
// holding a shield?
- out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::SHIELD_ARMOR]> //state.getShieldIndex()
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::SHIELD_ARMOR])); //shieldIndex
// wearing chest armor?
- out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::BODY_ARMOR]> //state.getChestArmIndex()
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::BODY_ARMOR])); //chestArmIndex
// wearing spiritual armor?
- out->writeSint32LE(0); //hex offset for <_world->_player->_armor[Chr::ChrArmorType::MAGIC_ARMOR]> //state.getSprtArmIndex()
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::MAGIC_ARMOR])); //sprtArmIndex
// TODO:
out->writeSint16LE(0xffff); // ???? - always FFFF
@@ -122,13 +176,13 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint16LE(0xffff); // ???? - always FFFF
// did a character just escape?
- out->writeSint32LE(0); //state.getRunCharHexOffset()
+ out->writeSint32LE(GET_HEX_CHR_OFFSET(_running)); //getRunCharHexOffset() == getHexOffsetForChr(running)
// players experience points
- out->writeSint32LE(_world->_player->_context._experience);
+ out->writeSint32LE(playerContext._experience);
- out->writeSint16LE(0); //state.getAim()
- out->writeSint16LE(0); //state.getOpponentAim()
+ out->writeSint16LE(0); //TODO: state.getAim()
+ out->writeSint16LE(0); //TODO: state.getOpponentAim()
// TODO:
out->writeSint16LE(0x0000); // always 0
@@ -136,33 +190,96 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint16LE(0x0000); // always 0
// Base character stats
- out->writeByte(_world->_player->_physicalStrength); //state.getBasePhysStr()
- out->writeByte(_world->_player->_physicalHp); //state.getBasePhysHp()
- out->writeByte(_world->_player->_naturalArmor); //state.getBasePhysArm()
- out->writeByte(_world->_player->_physicalAccuracy); //state.getBasePhysAcc()
- out->writeByte(_world->_player->_spiritualStength); //state.getBaseSprtStr()
- out->writeByte(_world->_player->_spiritialHp); //state.getBaseSprtHp()
- out->writeByte(_world->_player->_resistanceToMagic); //state.getBaseSprtArm()
- out->writeByte(_world->_player->_spiritualAccuracy); //state.getBaseSprtAcc()
- out->writeByte(_world->_player->_runningSpeed); //state.getBaseRunSpeed()
+ // TODO: are these *base* btw? looks like we don't want to save *current* stats
+ out->writeByte(player->_physicalStrength); //state.getBasePhysStr()
+ out->writeByte(player->_physicalHp); //state.getBasePhysHp()
+ out->writeByte(player->_naturalArmor); //state.getBasePhysArm()
+ out->writeByte(player->_physicalAccuracy); //state.getBasePhysAcc()
+ out->writeByte(player->_spiritualStength); //state.getBaseSprtStr()
+ out->writeByte(player->_spiritialHp); //state.getBaseSprtHp()
+ out->writeByte(player->_resistanceToMagic); //state.getBaseSprtArm()
+ out->writeByte(player->_spiritualAccuracy); //state.getBaseSprtAcc()
+ out->writeByte(player->_runningSpeed); //state.getBaseRunSpeed()
// TODO:
out->writeByte(0x0A); // ???? - always seems to be 0x0A
- /*
// write user vars
- for (short var : state.getUserVars())
- out->->writeSint16LE(var);
-
+ for (uint32 i = 0; i < 26 * 9; ++i)
+ out->writeSint16LE(playerContext._userVariables[i]);
+
// write updated info for all scenes
- out.write(state.getSceneData());
+ Common::Array<Scene *> &orderedScenes = _world->_orderedScenes;
+ for (uint32 i = 0; i < orderedScenes.size(); ++i) {
+ Scene *scene = orderedScenes[i];
+ if (scene != _world->_storageScene) {
+ out->writeSint16LE(0); //TODO: scene.resourceId
+ out->writeSint16LE(scene->_worldY);
+ out->writeSint16LE(scene->_worldX);
+ out->writeByte(scene->_blocked[NORTH] ? 0x01 : 0x00);
+ out->writeByte(scene->_blocked[SOUTH] ? 0x01 : 0x00);
+ out->writeByte(scene->_blocked[EAST] ? 0x01 : 0x00);
+ out->writeByte(scene->_blocked[WEST] ? 0x01 : 0x00);
+ out->writeSint16LE(scene->_soundFrequency);
+ out->writeByte(scene->_soundType);
+ // the following two bytes are currently unknown
+ out->writeByte(0);
+ out->writeByte(0);
+ out->writeByte(scene->_visited ? 0x01 : 0x00);
+ }
+ }
// write updated info for all characters
- out.write(state.getChrData());
+ Common::Array<Chr *> &orderedChrs = _world->_orderedChrs;
+ for (uint32 i = 0; i < orderedChrs.size(); ++i) {
+ Chr *chr = orderedChrs[i];
+ out->writeSint16LE(0); //TODO: chr.getResourceID()
+ out->writeSint16LE(0); //TODO: chr->_currentScene.getResourceID()
+ //TODO: here we want to write *current* stats
+ out->writeByte(chr->_physicalStrength);
+ out->writeByte(chr->_physicalHp);
+ out->writeByte(chr->_naturalArmor);
+ out->writeByte(chr->_physicalAccuracy);
+ out->writeByte(chr->_spiritualStength);
+ out->writeByte(chr->_spiritialHp);
+ out->writeByte(chr->_resistanceToMagic);
+ out->writeByte(chr->_spiritualAccuracy);
+ out->writeByte(chr->_runningSpeed);
+ out->writeByte(chr->_rejectsOffers);
+ out->writeByte(chr->_followsOpponent);
+ // bytes 16-20 are unknown
+ out->writeByte(0);
+ out->writeByte(0);
+ out->writeByte(0);
+ out->writeByte(0);
+ out->writeByte(0);
+ out->writeByte(chr->_weaponDamage1);
+ out->writeByte(chr->_weaponDamage2);
+ }
// write updated info for all objects
- out.write(state.getObjData());
- */
+ Common::Array<Obj *> &orderedObjs = _world->_orderedObjs;
+ for (uint32 i = 0; i < orderedObjs.size(); ++i) {
+ Obj *obj = orderedObjs[i];
+ Scene *location = obj->_currentScene;
+ Chr *owner = obj->_currentOwner;
+
+ out->writeSint16LE(0); //TODO: obj.getResourceID()
+ out->writeSint16LE(0); //TODO: location == nullptr ? 0 : location.getResourceID());
+ out->writeSint16LE(0); //TODO: owner == nullptr ? 0 : owner.getResourceID());
+
+ // bytes 7-9 are unknown (always = 0)
+ out->writeByte(0);
+ out->writeByte(0);
+ out->writeByte(0);
+
+ out->writeByte(obj->_accuracy);
+ out->writeByte(obj->_value);
+ out->writeByte(obj->_type);
+ out->writeByte(obj->_damage);
+ out->writeByte(obj->_attackType);
+ out->writeSint16LE(obj->_numberOfUses);
+ }
out->finalize();
if (out->err()) {
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index b1d793b..1c33e16 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -211,6 +211,7 @@ public:
Common::Error saveGameState(int slot, const Common::String &description);
private:
+ int getSceneIndex(Scene *scene) const;
int saveGame(const Common::String &fileName, const Common::String &descriptionString);
Common::String getSavegameFilename(int16 slotId) const;
Commit: 5d804f379ce77f0dd5eb43cfa5c2d18aa2de3585
https://github.com/scummvm/scummvm/commit/5d804f379ce77f0dd5eb43cfa5c2d18aa2de3585
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-27T17:27:18+06:00
Commit Message:
WAGE: Refine saveGame()
Base/Current stats fix + loopNum, aim, opponentAim saving.
Changed paths:
engines/wage/saveload.cpp
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index 7132162..2c4a23f 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -145,7 +145,7 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
// More Counters
out->writeSint32LE(playerContext._visits); //visitNum
- out->writeSint32LE(0); //TODO: state.getLoopNum()
+ out->writeSint32LE(_loopCount); //loopNum
out->writeSint32LE(playerContext._kills); //killNum
// Hex offset to player character
@@ -181,8 +181,8 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
// players experience points
out->writeSint32LE(playerContext._experience);
- out->writeSint16LE(0); //TODO: state.getAim()
- out->writeSint16LE(0); //TODO: state.getOpponentAim()
+ out->writeSint16LE(_aim); //aim
+ out->writeSint16LE(_opponentAim); //opponentAim
// TODO:
out->writeSint16LE(0x0000); // always 0
@@ -190,16 +190,15 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint16LE(0x0000); // always 0
// Base character stats
- // TODO: are these *base* btw? looks like we don't want to save *current* stats
- out->writeByte(player->_physicalStrength); //state.getBasePhysStr()
- out->writeByte(player->_physicalHp); //state.getBasePhysHp()
- out->writeByte(player->_naturalArmor); //state.getBasePhysArm()
- out->writeByte(player->_physicalAccuracy); //state.getBasePhysAcc()
- out->writeByte(player->_spiritualStength); //state.getBaseSprtStr()
- out->writeByte(player->_spiritialHp); //state.getBaseSprtHp()
- out->writeByte(player->_resistanceToMagic); //state.getBaseSprtArm()
- out->writeByte(player->_spiritualAccuracy); //state.getBaseSprtAcc()
- out->writeByte(player->_runningSpeed); //state.getBaseRunSpeed()
+ out->writeByte(playerContext._statVariables[PHYS_STR_BAS]); //state.getBasePhysStr()
+ out->writeByte(playerContext._statVariables[PHYS_HIT_BAS]); //state.getBasePhysHp()
+ out->writeByte(playerContext._statVariables[PHYS_ARM_BAS]); //state.getBasePhysArm()
+ out->writeByte(playerContext._statVariables[PHYS_ACC_BAS]); //state.getBasePhysAcc()
+ out->writeByte(playerContext._statVariables[SPIR_STR_BAS]); //state.getBaseSprtStr()
+ out->writeByte(playerContext._statVariables[SPIR_HIT_BAS]); //state.getBaseSprtHp()
+ out->writeByte(playerContext._statVariables[SPIR_ARM_BAS]); //state.getBaseSprtArm()
+ out->writeByte(playerContext._statVariables[SPIR_ACC_BAS]); //state.getBaseSprtAcc()
+ out->writeByte(playerContext._statVariables[PHYS_SPE_BAS]); //state.getBaseRunSpeed()
// TODO:
out->writeByte(0x0A); // ???? - always seems to be 0x0A
@@ -235,16 +234,16 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
Chr *chr = orderedChrs[i];
out->writeSint16LE(0); //TODO: chr.getResourceID()
out->writeSint16LE(0); //TODO: chr->_currentScene.getResourceID()
- //TODO: here we want to write *current* stats
- out->writeByte(chr->_physicalStrength);
- out->writeByte(chr->_physicalHp);
- out->writeByte(chr->_naturalArmor);
- out->writeByte(chr->_physicalAccuracy);
- out->writeByte(chr->_spiritualStength);
- out->writeByte(chr->_spiritialHp);
- out->writeByte(chr->_resistanceToMagic);
- out->writeByte(chr->_spiritualAccuracy);
- out->writeByte(chr->_runningSpeed);
+ Context &chrContext = chr->_context;
+ out->writeByte(chrContext._statVariables[PHYS_STR_CUR]);
+ out->writeByte(chrContext._statVariables[PHYS_HIT_CUR]);
+ out->writeByte(chrContext._statVariables[PHYS_ARM_CUR]);
+ out->writeByte(chrContext._statVariables[PHYS_ACC_CUR]);
+ out->writeByte(chrContext._statVariables[SPIR_STR_CUR]);
+ out->writeByte(chrContext._statVariables[SPIR_HIT_CUR]);
+ out->writeByte(chrContext._statVariables[SPIR_ARM_CUR]);
+ out->writeByte(chrContext._statVariables[SPIR_ACC_CUR]);
+ out->writeByte(chrContext._statVariables[PHYS_SPE_CUR]);
out->writeByte(chr->_rejectsOffers);
out->writeByte(chr->_followsOpponent);
// bytes 16-20 are unknown
Commit: 6b21b1f89365bd77494940ec918212069238cc70
https://github.com/scummvm/scummvm/commit/6b21b1f89365bd77494940ec918212069238cc70
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-27T17:38:43+06:00
Commit Message:
WAGE: Add World's _signature
Changed paths:
engines/wage/saveload.cpp
engines/wage/world.cpp
engines/wage/world.h
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index 2c4a23f..6085255 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -138,7 +138,7 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint32LE(objsHexOffset);
// Unique 8-byte World Signature
- out->writeSint32LE(0); //TODO: 8-byte ints? seriously?
+ out->writeSint32LE(_world->_signature); //8-byte ints? seriously? (uses 4 bytes in java code too)
Chr *player = _world->_player;
Context &playerContext = player->_context;
diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp
index 0e40e11..8b89060 100644
--- a/engines/wage/world.cpp
+++ b/engines/wage/world.cpp
@@ -69,6 +69,7 @@ World::World(WageEngine *engine) {
_globalScript = nullptr;
_player = nullptr;
+ _signature = 0;
_weaponMenuDisabled = true;
@@ -146,7 +147,8 @@ bool World::loadWorld(Common::MacResManager *resMan) {
res = resMan->getResource(MKTAG('V','E','R','S'), resArray[0]);
- res->skip(10);
+ _signature = res->readSint32LE();
+ res->skip(6);
byte b = res->readByte();
_weaponMenuDisabled = (b != 0);
if (b != 0 && b != 1)
diff --git a/engines/wage/world.h b/engines/wage/world.h
index 9eac072..918616c 100644
--- a/engines/wage/world.h
+++ b/engines/wage/world.h
@@ -92,6 +92,7 @@ public:
Patterns *_patterns;
Scene *_storageScene;
Chr *_player;
+ int _signature;
//List<MoveListener> moveListeners;
Common::String *_gameOverMessage;
Commit: 35883517994efbcef9b5eb429b3888235745dea8
https://github.com/scummvm/scummvm/commit/35883517994efbcef9b5eb429b3888235745dea8
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-27T17:51:00+06:00
Commit Message:
WAGE: Refine saveGame() once more
_resourceId is added to entities, so saveGame() can access these ids and
save them.
Changed paths:
engines/wage/entities.cpp
engines/wage/entities.h
engines/wage/saveload.cpp
engines/wage/world.cpp
diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp
index 43ac6c8..b2babba 100644
--- a/engines/wage/entities.cpp
+++ b/engines/wage/entities.cpp
@@ -80,6 +80,8 @@ Context::Context() {
}
Scene::Scene() {
+ _resourceId = 0;
+
_script = NULL;
_design = NULL;
_textBounds = NULL;
@@ -104,6 +106,8 @@ Scene::Scene(Common::String name, Common::SeekableReadStream *data) {
_classType = SCENE;
_design = new Design(data);
+ _resourceId = 0;
+
_script = NULL;
_textBounds = NULL;
_fontSize = 0;
@@ -221,6 +225,7 @@ Designed *Scene::lookUpEntity(int x, int y) {
Obj::Obj() : _currentOwner(NULL), _currentScene(NULL) {
_index = 0;
+ _resourceId = 0;
_namePlural = false;
_value = 0;
_attackType = 0;
@@ -231,7 +236,9 @@ Obj::Obj() : _currentOwner(NULL), _currentScene(NULL) {
_damage = 0;
}
-Obj::Obj(Common::String name, Common::SeekableReadStream *data) {
+Obj::Obj(Common::String name, Common::SeekableReadStream *data, int resourceId) {
+ _resourceId = resourceId;
+
_name = name;
_classType = OBJ;
_currentOwner = NULL;
@@ -322,6 +329,7 @@ Chr::Chr(Common::String name, Common::SeekableReadStream *data) {
_design = new Design(data);
_index = 0;
+ _resourceId = 0;
_currentScene = NULL;
setDesignBounds(readRect(data));
diff --git a/engines/wage/entities.h b/engines/wage/entities.h
index 9e706f0..f327270 100644
--- a/engines/wage/entities.h
+++ b/engines/wage/entities.h
@@ -152,6 +152,7 @@ public:
Chr(Common::String name, Common::SeekableReadStream *data);
int _index;
+ int _resourceId;
Common::String _initialScene;
int _gender;
bool _nameProperNoun;
@@ -229,7 +230,7 @@ public:
class Obj : public Designed {
public:
Obj();
- Obj(Common::String name, Common::SeekableReadStream *data);
+ Obj(Common::String name, Common::SeekableReadStream *data, int resourceId);
~Obj();
enum ObjectType {
@@ -256,6 +257,7 @@ public:
public:
int _index;
+ int _resourceId;
bool _namePlural;
uint _value;
int _attackType;
@@ -301,6 +303,8 @@ public:
RANDOM = 1
};
+ int _resourceId;
+
Script *_script;
Common::String _text;
Common::Rect *_textBounds;
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index 6085255..a204757 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -212,7 +212,7 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
for (uint32 i = 0; i < orderedScenes.size(); ++i) {
Scene *scene = orderedScenes[i];
if (scene != _world->_storageScene) {
- out->writeSint16LE(0); //TODO: scene.resourceId
+ out->writeSint16LE(scene->_resourceId);
out->writeSint16LE(scene->_worldY);
out->writeSint16LE(scene->_worldX);
out->writeByte(scene->_blocked[NORTH] ? 0x01 : 0x00);
@@ -232,8 +232,8 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
Common::Array<Chr *> &orderedChrs = _world->_orderedChrs;
for (uint32 i = 0; i < orderedChrs.size(); ++i) {
Chr *chr = orderedChrs[i];
- out->writeSint16LE(0); //TODO: chr.getResourceID()
- out->writeSint16LE(0); //TODO: chr->_currentScene.getResourceID()
+ out->writeSint16LE(chr->_resourceId);
+ out->writeSint16LE(chr->_currentScene->_resourceId);
Context &chrContext = chr->_context;
out->writeByte(chrContext._statVariables[PHYS_STR_CUR]);
out->writeByte(chrContext._statVariables[PHYS_HIT_CUR]);
@@ -263,9 +263,9 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
Scene *location = obj->_currentScene;
Chr *owner = obj->_currentOwner;
- out->writeSint16LE(0); //TODO: obj.getResourceID()
- out->writeSint16LE(0); //TODO: location == nullptr ? 0 : location.getResourceID());
- out->writeSint16LE(0); //TODO: owner == nullptr ? 0 : owner.getResourceID());
+ out->writeSint16LE(obj->_resourceId);
+ out->writeSint16LE(location == nullptr ? 0 : location->_resourceId);
+ out->writeSint16LE(owner == nullptr ? 0 : owner->_resourceId);
// bytes 7-9 are unknown (always = 0)
out->writeByte(0);
diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp
index 8b89060..286ecdd 100644
--- a/engines/wage/world.cpp
+++ b/engines/wage/world.cpp
@@ -217,6 +217,8 @@ bool World::loadWorld(Common::MacResManager *resMan) {
delete res;
}
+
+ scene->_resourceId = *iter;
addScene(scene);
}
@@ -226,7 +228,7 @@ bool World::loadWorld(Common::MacResManager *resMan) {
for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
res = resMan->getResource(MKTAG('A','O','B','J'), *iter);
- addObj(new Obj(resMan->getResName(MKTAG('A','O','B','J'), *iter), res));
+ addObj(new Obj(resMan->getResName(MKTAG('A','O','B','J'), *iter), res, *iter));
}
// Load Characters
@@ -236,7 +238,7 @@ bool World::loadWorld(Common::MacResManager *resMan) {
for (iter = resArray.begin(); iter != resArray.end(); ++iter) {
res = resMan->getResource(MKTAG('A','C','H','R'), *iter);
Chr *chr = new Chr(resMan->getResName(MKTAG('A','C','H','R'), *iter), res);
-
+ chr->_resourceId = *iter;
addChr(chr);
// TODO: What if there's more than one player character?
if (chr->_playerCharacter)
Commit: a4f02c73837ef46f620872d8297cdc6cbf5119dc
https://github.com/scummvm/scummvm/commit/a4f02c73837ef46f620872d8297cdc6cbf5119dc
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-27T18:06:39+06:00
Commit Message:
WAGE: Move some code in saveGame()
Now flags, version, description and thumbnail are added in the end of
the file, thus making saves compatible with original ones.
Changed paths:
engines/wage/saveload.cpp
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index a204757..bc9a443 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -66,12 +66,16 @@
#define SAVEGAME_CURRENT_VERSION 1
//
-// Version 0 (ScummVM): first ScummVM version
+// Original saves format is supported.
+// ScummVM adds flags, description and thumbnail
+// in the end of the file (shouldn't make saves incompatible).
+//
+// Version 0 (original/ScummVM): first ScummVM version
//
namespace Wage {
-static const uint32 AGIflag = MKTAG('W', 'A', 'G', 'E');
+static const uint32 WAGEflag = MKTAG('W', 'A', 'G', 'E');
//TODO: make sure these are calculated right: (we add flag, description, etc)
#define VARS_INDEX 0x005E
@@ -109,23 +113,6 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
debug(9, "Successfully opened %s for writing", fileName.c_str());
}
- out->writeUint32BE(AGIflag);
-
- // Write description of saved game, limited to WAGE_SAVEDGAME_DESCRIPTION_LEN characters + terminating NUL
- const int WAGE_SAVEDGAME_DESCRIPTION_LEN = 127;
- char description[WAGE_SAVEDGAME_DESCRIPTION_LEN + 1];
-
- memset(description, 0, sizeof(description));
- strncpy(description, descriptionString.c_str(), WAGE_SAVEDGAME_DESCRIPTION_LEN);
- assert(WAGE_SAVEDGAME_DESCRIPTION_LEN + 1 == 128); // safety
- out->write(description, 128);
-
- out->writeByte(SAVEGAME_CURRENT_VERSION);
- debug(9, "Writing save game version (%d)", SAVEGAME_CURRENT_VERSION);
-
- // Thumbnail
- Graphics::saveThumbnail(*out);
-
// Counters
out->writeSint16LE(_world->_scenes.size()); //numScenes
out->writeSint16LE(_world->_chrs.size()); //numChars
@@ -280,6 +267,30 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint16LE(obj->_numberOfUses);
}
+ // the following is appended by ScummVM
+ out->writeUint32BE(WAGEflag);
+
+ // Write description of saved game, limited to WAGE_SAVEDGAME_DESCRIPTION_LEN characters + terminating NUL
+ const int WAGE_SAVEDGAME_DESCRIPTION_LEN = 127;
+ char description[WAGE_SAVEDGAME_DESCRIPTION_LEN + 1];
+
+ memset(description, 0, sizeof(description));
+ strncpy(description, descriptionString.c_str(), WAGE_SAVEDGAME_DESCRIPTION_LEN);
+ assert(WAGE_SAVEDGAME_DESCRIPTION_LEN + 1 == 128); // safety
+ out->write(description, 128);
+
+ out->writeByte(SAVEGAME_CURRENT_VERSION);
+ debug(9, "Writing save game version (%d)", SAVEGAME_CURRENT_VERSION);
+
+ // Thumbnail
+ Graphics::saveThumbnail(*out);
+
+ // this one to make checking easier:
+ // it couldn't be added to the beginning
+ // and we won't be able to find it in the middle,
+ // so these would be the last 4 bytes of the file
+ out->writeUint32BE(WAGEflag);
+
out->finalize();
if (out->err()) {
warning("Can't write file '%s'. (Disk full?)", fileName.c_str());
Commit: 18476dc752efd9888222b2b61d30a88648486fbd
https://github.com/scummvm/scummvm/commit/18476dc752efd9888222b2b61d30a88648486fbd
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-27T21:38:10+06:00
Commit Message:
WAGE: Add loadGame() sketch
Changed paths:
engines/wage/saveload.cpp
engines/wage/wage.cpp
engines/wage/wage.h
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index bc9a443..4b38e5b 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -302,6 +302,190 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
return result;
}
+int WageEngine::loadGame(int slotId) {
+ Common::InSaveFile *data;
+ Common::String fileName = getSavegameFilename(slotId);
+
+ debug(9, "WageEngine::loadGame(%d)", slotId);
+ if (!(data = _saveFileMan->openForLoading(fileName))) {
+ warning("Can't open file '%s', game not loaded", fileName.c_str());
+ return -1;
+ } else {
+ debug(9, "Successfully opened %s for reading", fileName.c_str());
+ }
+
+ // Counters
+ int numScenes = data->readSint16LE();
+ int numChars = data->readSint16LE();
+ int numObjs = data->readSint16LE();
+
+ // Hex Offsets
+ int chrsHexOffset = data->readSint32LE();
+ int objsHexOffset = data->readSint32LE();
+
+ // Unique 8-byte World Signature
+ _world->_signature = data->readSint32LE();
+
+ //Chr *player = _world->_player;
+ //Context &playerContext = player->_context;
+
+ // More Counters
+ int visitNum = data->readSint32LE(); //visitNum @ playerContext._visits
+ _loopCount = data->readSint32LE(); //loopNum
+ int killNum = data->readSint32LE(); //killNum @ playerContext._kills
+
+ // Hex offset to player character
+ int playerOffset = data->readSint32LE();
+
+ // character in this scene?
+ int presCharOffset = data->readSint32LE();
+
+ // Hex offset to current scene
+ int currentSceneOffset = data->readSint32LE();
+
+ // wearing a helmet?
+ int helmetOffset = data->readSint32LE(); //helmetIndex @ player->_armor[Chr::ChrArmorType::HEAD_ARMOR]
+
+ // holding a shield?
+ int shieldOffset = data->readSint32LE(); //shieldIndex @ player->_armor[Chr::ChrArmorType::SHIELD_ARMOR]
+
+ // wearing chest armor?
+ int armorOffset = data->readSint32LE(); //chestArmIndex @ player->_armor[Chr::ChrArmorType::BODY_ARMOR]
+
+ // wearing spiritual armor?
+ int spiritualArmorOffset = data->readSint32LE(); //sprtArmIndex @ player->_armor[Chr::ChrArmorType::MAGIC_ARMOR]
+
+ data->readSint16LE(); // FFFF
+ data->readSint16LE(); // FFFF
+ data->readSint16LE(); // FFFF
+ data->readSint16LE(); // FFFF
+
+ int runCharOffset = data->readSint32LE();
+
+ // players experience points
+ int exp = data->readSint32LE(); // @ playerContext._experience
+
+ _aim = data->readSint16LE(); //aim
+ _opponentAim = data->readSint16LE(); //opponentAim
+
+ data->readSint16LE(); // 0000
+ data->readSint16LE(); // 0000
+ data->readSint16LE(); // 0000
+
+ // Base character stats
+ int basePhysStr = data->readByte(); // @ playerContext._statVariables[PHYS_STR_BAS]
+ int basePhysHp = data->readByte(); // @ playerContext._statVariables[PHYS_HIT_BAS]
+ int basePhysArm = data->readByte(); // @ playerContext._statVariables[PHYS_ARM_BAS]
+ int basePhysAcc = data->readByte(); // @ playerContext._statVariables[PHYS_ACC_BAS]
+ int baseSprtStr = data->readByte(); // @ playerContext._statVariables[SPIR_STR_BAS]
+ int baseSprtHp = data->readByte(); // @ playerContext._statVariables[SPIR_HIT_BAS]
+ int baseSprtArm = data->readByte(); // @ playerContext._statVariables[SPIR_ARM_BAS]
+ int baseSprtAcc = data->readByte(); // @ playerContext._statVariables[SPIR_ACC_BAS]
+ int baseRunSpeed = data->readByte(); // @ playerContext._statVariables[PHYS_SPE_BAS]
+
+ data->readByte(); // 0x0A?
+
+ // write user vars
+ for (uint32 i = 0; i < 26 * 9; ++i)
+ data->readSint16LE(); // @ playerContext._userVariables[i]
+
+ // write updated info for all scenes
+ for (uint32 i = 0; i < numScenes; ++i) {
+ data->readSint16LE(); // @ scene->_resourceId
+ data->readSint16LE(); // @ scene->_worldY
+ data->readSint16LE(); // @ scene->_worldX
+ data->readByte(); // @ scene->_blocked[NORTH]
+ data->readByte(); // @ scene->_blocked[SOUTH]
+ data->readByte(); // @ scene->_blocked[EAST]
+ data->readByte(); // @ scene->_blocked[WEST]
+ data->readSint16LE(); // @ scene->_soundFrequency
+ data->readByte(); // @ scene->_soundType
+ // the following two bytes are currently unknown
+ data->readByte();
+ data->readByte();
+ data->readByte(); // @ scene->_visited
+ }
+
+ // write updated info for all characters
+ Common::Array<Chr *> &orderedChrs = _world->_orderedChrs;
+ for (uint32 i = 0; i < orderedChrs.size(); ++i) {
+ int resourceId = data->readSint16LE();
+ int sceneResourceId = data->readSint16LE();
+
+ int strength = data->readByte(); // @ chrContext._statVariables[PHYS_STR_CUR]
+ int hp = data->readByte(); // @ chrContext._statVariables[PHYS_HIT_CUR]
+ int armor = data->readByte(); // @ chrContext._statVariables[PHYS_ARM_CUR]
+ int accuracy = data->readByte(); // @ chrContext._statVariables[PHYS_ACC_CUR]
+ int spirStrength = data->readByte(); // @ chrContext._statVariables[SPIR_STR_CUR]
+ int spirHp = data->readByte(); // @ chrContext._statVariables[SPIR_HIT_CUR]
+ int spirArmor = data->readByte(); // @ chrContext._statVariables[SPIR_ARM_CUR]
+ int spirAccuracy = data->readByte(); // @ chrContext._statVariables[SPIR_ACC_CUR]
+ int speed = data->readByte(); // @ chrContext._statVariables[PHYS_SPE_CUR]
+ int rejectsOffers = data->readByte(); // @ chr->_rejectsOffers
+ int followsOpponent = data->readByte(); // @ chr->_followsOpponent
+
+ // bytes 16-20 are unknown
+ data->readByte();
+ data->readByte();
+ data->readByte();
+ data->readByte();
+ data->readByte();
+
+ data->readByte(); // @ chr->_weaponDamage1
+ data->readByte(); // @ chr->_weaponDamage2
+ }
+
+ // write updated info for all objects
+ for (uint32 i = 0; i < numObjs; ++i) {
+ int resourceId = data->readSint16LE();
+ int locationResourceId = data->readSint16LE();
+ int ownerResourceId = data->readSint16LE();
+
+ // bytes 7-9 are unknown (always = 0)
+ data->readByte();
+ data->readByte();
+ data->readByte();
+
+ data->readByte(); // @ obj->_accuracy
+ data->readByte(); // @ obj->_value
+ data->readByte(); // @ obj->_type
+ data->readByte(); // @ obj->_damage
+ data->readByte(); // @ obj->_attackType
+ data->readSint16LE(); // @ obj->_numberOfUses
+ }
+
+ // the following is appended by ScummVM
+ if (data->pos() < data->size()) {
+ int scummvmWageFlag = data->readUint32BE();
+
+ if (scummvmWageFlag != WAGEflag) {
+ warning("Extra bytes after original save's information found, but that's not ScummVM's");
+ delete data;
+ return 0;
+ }
+
+ // Write description of saved game, limited to WAGE_SAVEDGAME_DESCRIPTION_LEN characters + terminating NUL
+ const int WAGE_SAVEDGAME_DESCRIPTION_LEN = 127;
+ char description[WAGE_SAVEDGAME_DESCRIPTION_LEN + 1];
+ data->read(description, 128);
+ if (description[WAGE_SAVEDGAME_DESCRIPTION_LEN] != 0) {
+ warning("Description's last byte is not '\0'");
+ description[WAGE_SAVEDGAME_DESCRIPTION_LEN] = 0;
+ }
+
+ int version = data->readByte();
+ if (version != SAVEGAME_CURRENT_VERSION) {
+ warning("Reading version %d while current is %d", version, SAVEGAME_CURRENT_VERSION);
+ }
+
+ // Thumbnail
+ Graphics::loadThumbnail(*data);
+ }
+
+ delete data;
+ return 0;
+}
+
Common::String WageEngine::getSavegameFilename(int16 slotId) const {
Common::String saveLoadSlot = _targetName;
saveLoadSlot += Common::String::format(".%.3d", slotId);
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index 567e276..f1ed5d4 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -45,6 +45,7 @@
*
*/
+#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/error.h"
#include "common/events.h"
@@ -126,8 +127,13 @@ Common::Error WageEngine::run() {
_temporarilyHidden = true;
performInitialSetup();
- Common::String input("look");
- processTurn(&input, NULL);
+ if (ConfMan.hasKey("save_slot")) {
+ int saveSlot = ConfMan.getInt("save_slot");
+ loadGame(saveSlot);
+ } else {
+ Common::String input("look");
+ processTurn(&input, NULL);
+ }
_temporarilyHidden = false;
_shouldQuit = false;
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index 1c33e16..5507ed9 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -213,6 +213,7 @@ public:
private:
int getSceneIndex(Scene *scene) const;
int saveGame(const Common::String &fileName, const Common::String &descriptionString);
+ int loadGame(int slotId);
Common::String getSavegameFilename(int16 slotId) const;
public:
Commit: a854217bd67c0e9ac8df552064dbfcaf6fd83024
https://github.com/scummvm/scummvm/commit/a854217bd67c0e9ac8df552064dbfcaf6fd83024
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-28T15:21:14+06:00
Commit Message:
WAGE: Refine loadGame()
It now actually does the loading.
Changed paths:
engines/wage/saveload.cpp
engines/wage/wage.cpp
engines/wage/wage.h
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index 4b38e5b..654812a 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -88,19 +88,86 @@ static const uint32 WAGEflag = MKTAG('W', 'A', 'G', 'E');
#define GET_HEX_OFFSET(ptr, baseOffset, entrySize) ((ptr) == nullptr ? -1 : ((baseOffset) + (entrySize) * (ptr)->_index))
#define GET_HEX_CHR_OFFSET(ptr) GET_HEX_OFFSET((ptr), chrsHexOffset, CHR_SIZE)
#define GET_HEX_OBJ_OFFSET(ptr) GET_HEX_OFFSET((ptr), objsHexOffset, OBJ_SIZE)
-#define GET_HEX_SCENE_OFFSET(ptr) ((ptr) == nullptr ? -1 : (SCENES_INDEX + getSceneIndex(_world->_player->_currentScene) * SCENE_SIZE))
+#define GET_HEX_SCENE_OFFSET(ptr) ((ptr) == nullptr ? -1 : \
+ ((ptr) == _world->_storageScene ? 0 : (SCENES_INDEX + getSceneIndex(_world->_player->_currentScene) * SCENE_SIZE)))
int WageEngine::getSceneIndex(Scene *scene) const {
assert(scene);
Common::Array<Scene *> &orderedScenes = _world->_orderedScenes;
for (uint32 i = 0; i < orderedScenes.size(); ++i) {
- if (orderedScenes[i] == scene) return i;
+ if (orderedScenes[i] == scene) return i-1;
}
warning("Scene's index not found");
return -1;
}
+Obj *WageEngine::getObjByOffset(int offset, int objBaseOffset) const {
+ int objIndex = -1;
+
+ if (offset != 0xFFFF) {
+ objIndex = (offset - objBaseOffset) / CHR_SIZE;
+ }
+
+ if (objIndex >= 0 && objIndex < _world->_orderedObjs.size()) {
+ return _world->_orderedObjs[objIndex];
+ }
+
+ return nullptr;
+}
+
+Chr *WageEngine::getChrById(int resId) const {
+ Common::Array<Chr *> &orderedChrs = _world->_orderedChrs;
+ for (uint32 i = 0; i < orderedChrs.size(); ++i) {
+ if (orderedChrs[i]->_resourceId == resId)
+ return orderedChrs[i];
+ }
+
+ return nullptr;
+}
+
+Chr *WageEngine::getChrByOffset(int offset, int chrBaseOffset) const {
+ int chrIndex = -1;
+
+ if (offset != 0xFFFF) {
+ chrIndex = (offset - chrBaseOffset) / CHR_SIZE;
+ }
+
+ if (chrIndex >= 0 && chrIndex < _world->_orderedChrs.size()) {
+ return _world->_orderedChrs[chrIndex];
+ }
+
+ return nullptr;
+}
+
+Scene *WageEngine::getSceneById(int resId) const {
+ Common::Array<Scene *> &orderedScenes = _world->_orderedScenes;
+ for (uint32 i = 0; i < orderedScenes.size(); ++i) {
+ if (orderedScenes[i]->_resourceId == resId)
+ return orderedScenes[i];
+ }
+
+ return nullptr;
+}
+
+Scene *WageEngine::getSceneByOffset(int offset) const {
+ int sceneIndex = -1;
+
+ if (offset != 0xFFFF) {
+ if (offset == 0)
+ sceneIndex = 0;
+ else
+ sceneIndex = 1 + (offset - SCENES_INDEX) / SCENE_SIZE;
+ }
+
+ if (sceneIndex >= 0 && sceneIndex < _world->_orderedScenes.size()) {
+ if (sceneIndex == 0) return _world->_storageScene;
+ return _world->_orderedScenes[sceneIndex];
+ }
+
+ return nullptr;
+}
+
int WageEngine::saveGame(const Common::String &fileName, const Common::String &descriptionString) {
Common::OutSaveFile *out;
int result = 0;
@@ -324,15 +391,18 @@ int WageEngine::loadGame(int slotId) {
int objsHexOffset = data->readSint32LE();
// Unique 8-byte World Signature
- _world->_signature = data->readSint32LE();
-
- //Chr *player = _world->_player;
- //Context &playerContext = player->_context;
+ int signature = data->readSint32LE();
+ if (_world->_signature != signature) {
+ warning("This saved game is for a different world, please select another one");
+ warning("World signature = %d, save signature = %d", _world->_signature, signature);
+ delete data;
+ return -1;
+ }
// More Counters
- int visitNum = data->readSint32LE(); //visitNum @ playerContext._visits
- _loopCount = data->readSint32LE(); //loopNum
- int killNum = data->readSint32LE(); //killNum @ playerContext._kills
+ int visitNum = data->readSint32LE(); //visitNum
+ int loopNum = data->readSint32LE(); //loopNum
+ int killNum = data->readSint32LE(); //killNum
// Hex offset to player character
int playerOffset = data->readSint32LE();
@@ -343,17 +413,41 @@ int WageEngine::loadGame(int slotId) {
// Hex offset to current scene
int currentSceneOffset = data->readSint32LE();
+ // find player and current scene
+ Chr *player = getChrByOffset(playerOffset, chrsHexOffset);
+ if (player == nullptr) {
+ warning("Invalid Character! Aborting load.");
+ delete data;
+ return -1;
+ }
+
+ Scene *currentScene = getSceneByOffset(currentSceneOffset);
+ if (currentScene == nullptr) {
+ warning("Invalid Scene! Aborting load.");
+ delete data;
+ return -1;
+ }
+
+ // set player character
+ _world->_player = player;
+
+ // set current scene
+ player->_currentScene = currentScene;
+
+ // clear the players inventory list
+ player->_inventory.clear();
+
// wearing a helmet?
- int helmetOffset = data->readSint32LE(); //helmetIndex @ player->_armor[Chr::ChrArmorType::HEAD_ARMOR]
+ int helmetOffset = data->readSint32LE(); //helmetIndex
// holding a shield?
- int shieldOffset = data->readSint32LE(); //shieldIndex @ player->_armor[Chr::ChrArmorType::SHIELD_ARMOR]
+ int shieldOffset = data->readSint32LE(); //shieldIndex
// wearing chest armor?
- int armorOffset = data->readSint32LE(); //chestArmIndex @ player->_armor[Chr::ChrArmorType::BODY_ARMOR]
+ int armorOffset = data->readSint32LE(); //chestArmIndex
// wearing spiritual armor?
- int spiritualArmorOffset = data->readSint32LE(); //sprtArmIndex @ player->_armor[Chr::ChrArmorType::MAGIC_ARMOR]
+ int spiritualArmorOffset = data->readSint32LE(); //sprtArmIndex
data->readSint16LE(); // FFFF
data->readSint16LE(); // FFFF
@@ -365,64 +459,118 @@ int WageEngine::loadGame(int slotId) {
// players experience points
int exp = data->readSint32LE(); // @ playerContext._experience
- _aim = data->readSint16LE(); //aim
- _opponentAim = data->readSint16LE(); //opponentAim
+ int aim = data->readSint16LE(); //aim
+ int opponentAim = data->readSint16LE(); //opponentAim
data->readSint16LE(); // 0000
data->readSint16LE(); // 0000
data->readSint16LE(); // 0000
// Base character stats
- int basePhysStr = data->readByte(); // @ playerContext._statVariables[PHYS_STR_BAS]
- int basePhysHp = data->readByte(); // @ playerContext._statVariables[PHYS_HIT_BAS]
- int basePhysArm = data->readByte(); // @ playerContext._statVariables[PHYS_ARM_BAS]
- int basePhysAcc = data->readByte(); // @ playerContext._statVariables[PHYS_ACC_BAS]
- int baseSprtStr = data->readByte(); // @ playerContext._statVariables[SPIR_STR_BAS]
- int baseSprtHp = data->readByte(); // @ playerContext._statVariables[SPIR_HIT_BAS]
- int baseSprtArm = data->readByte(); // @ playerContext._statVariables[SPIR_ARM_BAS]
- int baseSprtAcc = data->readByte(); // @ playerContext._statVariables[SPIR_ACC_BAS]
- int baseRunSpeed = data->readByte(); // @ playerContext._statVariables[PHYS_SPE_BAS]
+ int basePhysStr = data->readByte();
+ int basePhysHp = data->readByte();
+ int basePhysArm = data->readByte();
+ int basePhysAcc = data->readByte();
+ int baseSprtStr = data->readByte();
+ int baseSprtHp = data->readByte();
+ int baseSprtArm = data->readByte();
+ int baseSprtAcc = data->readByte();
+ int baseRunSpeed = data->readByte();
+
+ // set player stats
+ Context &playerContext = player->_context;
+ // I'm setting player fields also, because those are used as base values in Chr::resetState()
+ playerContext._statVariables[PHYS_STR_BAS] = player->_physicalStrength = basePhysStr;
+ playerContext._statVariables[PHYS_HIT_BAS] = player->_physicalHp = basePhysHp;
+ playerContext._statVariables[PHYS_ARM_BAS] = player->_naturalArmor = basePhysArm;
+ playerContext._statVariables[PHYS_ACC_BAS] = player->_physicalAccuracy = basePhysAcc;
+ playerContext._statVariables[SPIR_STR_BAS] = player->_spiritualStength = baseSprtStr;
+ playerContext._statVariables[SPIR_HIT_BAS] = player->_spiritialHp = baseSprtHp;
+ playerContext._statVariables[SPIR_ARM_BAS] = player->_resistanceToMagic = baseSprtArm;
+ playerContext._statVariables[SPIR_ACC_BAS] = player->_spiritualAccuracy = baseSprtAcc;
+ playerContext._statVariables[PHYS_SPE_BAS] = player->_runningSpeed = baseRunSpeed;
+
+ // set visit#
+ playerContext._visits = visitNum;
+
+ // set monsters killed
+ playerContext._kills = killNum;
+
+ // set experience
+ playerContext._experience = exp;
+
+ // if a character is present, move it to this scene
+ // TODO: This is done in the engine object, would it be cleaner
+ // to move it here?
+ // well, it's actually down there now, now sure if that's "cleaner"
+ // when it's up there or down there
+
+ // if a character just ran away, let our engine know
+ // TODO: The current engine doesn't have a case for this, we
+ // should update it
+ // yep, I don't see such code anywhere in java, so not added it here
data->readByte(); // 0x0A?
- // write user vars
- for (uint32 i = 0; i < 26 * 9; ++i)
- data->readSint16LE(); // @ playerContext._userVariables[i]
-
- // write updated info for all scenes
- for (uint32 i = 0; i < numScenes; ++i) {
- data->readSint16LE(); // @ scene->_resourceId
- data->readSint16LE(); // @ scene->_worldY
- data->readSint16LE(); // @ scene->_worldX
- data->readByte(); // @ scene->_blocked[NORTH]
- data->readByte(); // @ scene->_blocked[SOUTH]
- data->readByte(); // @ scene->_blocked[EAST]
- data->readByte(); // @ scene->_blocked[WEST]
- data->readSint16LE(); // @ scene->_soundFrequency
- data->readByte(); // @ scene->_soundType
- // the following two bytes are currently unknown
- data->readByte();
- data->readByte();
- data->readByte(); // @ scene->_visited
+ // set all user variables
+ for (uint32 i = 0; i < 26 * 9; ++i) {
+ playerContext._userVariables[i] = data->readSint16LE();
}
- // write updated info for all characters
+ // update all scene stats
+ Common::Array<Scene *> &orderedScenes = _world->_orderedScenes;
+ if (numScenes != orderedScenes.size()) {
+ warning("scenes number in file (%d) differs from the one in world (%d)", numScenes, orderedScenes.size());
+ }
+ for (uint32 i = 0; i < orderedScenes.size(); ++i) {
+ Scene *scene = orderedScenes[i];
+ if (scene == _world->_storageScene) {
+ scene->_chrs.clear();
+ scene->_objs.clear();
+ } else {
+ int id = data->readSint16LE();
+
+ if (scene->_resourceId != id) {
+ warning("loadGame(): updating scenes: expected %d but got %d", scene->_resourceId, id);
+ data->skip(14); //2,2,1,1,1,1,2,1,1,1,1 down there
+ continue;
+ }
+
+ scene->_worldY = data->readSint16LE();
+ scene->_worldX = data->readSint16LE();
+ scene->_blocked[NORTH] = data->readByte() != 0;
+ scene->_blocked[SOUTH] = data->readByte() != 0;
+ scene->_blocked[EAST] = data->readByte() != 0;
+ scene->_blocked[WEST] = data->readByte() != 0;
+ scene->_soundFrequency = data->readSint16LE();
+ scene->_soundType = data->readByte();
+ // the following two bytes are currently unknown
+ data->readByte();
+ data->readByte();
+ scene->_visited = data->readByte() != 0;
+ }
+ }
+
+ // update all char locations and stats
Common::Array<Chr *> &orderedChrs = _world->_orderedChrs;
+ if (numChars != orderedChrs.size()) {
+ warning("characters number in file (%d) differs from the one in world (%d)", numChars, orderedChrs.size());
+ }
for (uint32 i = 0; i < orderedChrs.size(); ++i) {
int resourceId = data->readSint16LE();
int sceneResourceId = data->readSint16LE();
- int strength = data->readByte(); // @ chrContext._statVariables[PHYS_STR_CUR]
- int hp = data->readByte(); // @ chrContext._statVariables[PHYS_HIT_CUR]
- int armor = data->readByte(); // @ chrContext._statVariables[PHYS_ARM_CUR]
- int accuracy = data->readByte(); // @ chrContext._statVariables[PHYS_ACC_CUR]
- int spirStrength = data->readByte(); // @ chrContext._statVariables[SPIR_STR_CUR]
- int spirHp = data->readByte(); // @ chrContext._statVariables[SPIR_HIT_CUR]
- int spirArmor = data->readByte(); // @ chrContext._statVariables[SPIR_ARM_CUR]
- int spirAccuracy = data->readByte(); // @ chrContext._statVariables[SPIR_ACC_CUR]
- int speed = data->readByte(); // @ chrContext._statVariables[PHYS_SPE_CUR]
- int rejectsOffers = data->readByte(); // @ chr->_rejectsOffers
- int followsOpponent = data->readByte(); // @ chr->_followsOpponent
+ int strength = data->readByte();
+ int hp = data->readByte();
+ int armor = data->readByte();
+ int accuracy = data->readByte();
+ int spirStrength = data->readByte();
+ int spirHp = data->readByte();
+ int spirArmor = data->readByte();
+ int spirAccuracy = data->readByte();
+ int speed = data->readByte();
+ int rejectsOffers = data->readByte();
+ int followsOpponent = data->readByte();
// bytes 16-20 are unknown
data->readByte();
@@ -431,12 +579,38 @@ int WageEngine::loadGame(int slotId) {
data->readByte();
data->readByte();
- data->readByte(); // @ chr->_weaponDamage1
- data->readByte(); // @ chr->_weaponDamage2
+ int weaponDamage1 = data->readByte();
+ int weaponDamage2 = data->readByte();
+
+ Chr *chr = orderedChrs[i];
+ if (chr->_resourceId != resourceId) {
+ warning("loadGame(): updating chrs: expected %d but got %d", chr->_resourceId, resourceId);
+ continue;
+ }
+
+ chr->_currentScene = getSceneById(sceneResourceId);
+ Context &chrContext = chr->_context;
+ chrContext._statVariables[PHYS_STR_CUR] = strength;
+ chrContext._statVariables[PHYS_HIT_CUR] = hp;
+ chrContext._statVariables[PHYS_ARM_CUR] = armor;
+ chrContext._statVariables[PHYS_ACC_CUR] = accuracy;
+ chrContext._statVariables[SPIR_STR_CUR] = spirStrength;
+ chrContext._statVariables[SPIR_HIT_CUR] = spirHp;
+ chrContext._statVariables[SPIR_ARM_CUR] = spirArmor;
+ chrContext._statVariables[SPIR_ACC_CUR] = spirAccuracy;
+ chrContext._statVariables[PHYS_SPE_CUR] = speed;
+ chr->_rejectsOffers = rejectsOffers;
+ chr->_followsOpponent = followsOpponent;
+ chr->_weaponDamage1 = weaponDamage1;
+ chr->_weaponDamage2 = weaponDamage2;
}
- // write updated info for all objects
- for (uint32 i = 0; i < numObjs; ++i) {
+ // update all object locations and stats
+ Common::Array<Obj *> &orderedObjs = _world->_orderedObjs;
+ if (numObjs != orderedObjs.size()) {
+ warning("objects number in file (%d) differs from the one in world (%d)", numObjs, orderedObjs.size());
+ }
+ for (uint32 i = 0; i < orderedObjs.size(); ++i) {
int resourceId = data->readSint16LE();
int locationResourceId = data->readSint16LE();
int ownerResourceId = data->readSint16LE();
@@ -446,42 +620,97 @@ int WageEngine::loadGame(int slotId) {
data->readByte();
data->readByte();
- data->readByte(); // @ obj->_accuracy
- data->readByte(); // @ obj->_value
- data->readByte(); // @ obj->_type
- data->readByte(); // @ obj->_damage
- data->readByte(); // @ obj->_attackType
- data->readSint16LE(); // @ obj->_numberOfUses
- }
+ int accuracy = data->readByte();
+ int value = data->readByte();
+ int type = data->readByte();
+ int damage = data->readByte();
+ int attackType= data->readByte();
+ int numberOfUses = data->readSint16LE();
- // the following is appended by ScummVM
- if (data->pos() < data->size()) {
- int scummvmWageFlag = data->readUint32BE();
+ Obj *obj = orderedObjs[i];
+ if (obj->_resourceId != resourceId) {
+ warning("loadGame(): updating objs: expected %d but got %d", obj->_resourceId, resourceId);
+ continue;
+ }
+
+ if (ownerResourceId != 0) {
+ obj->setCurrentOwner(getChrById(ownerResourceId));
+ if (obj->_currentOwner == nullptr)
+ warning("loadGame(): updating objs: owner not found - char with id %d", ownerResourceId);
+ } else {
+ obj->setCurrentScene(getSceneById(locationResourceId));
+ if (obj->_currentScene == nullptr)
+ warning("loadGame(): updating objs: scene with id %d not found", ownerResourceId);
+ }
+
+ obj->_accuracy = accuracy;
+ obj->_value = value;
+ obj->_type = type;
+ obj->_damage = damage;
+ obj->_attackType = attackType;
+ obj->_numberOfUses = numberOfUses;
+ }
- if (scummvmWageFlag != WAGEflag) {
- warning("Extra bytes after original save's information found, but that's not ScummVM's");
- delete data;
- return 0;
+ // update inventories and scene contents
+ for (uint32 i = 0; i < orderedObjs.size(); ++i) {
+ Obj *obj = orderedObjs[i];
+ Chr *chr = obj->_currentOwner;
+ if (chr != nullptr) {
+ chr->_inventory.push_back(obj);
+ } else {
+ Scene *scene = obj->_currentScene;
+ scene->_objs.push_back(obj);
}
+ }
- // Write description of saved game, limited to WAGE_SAVEDGAME_DESCRIPTION_LEN characters + terminating NUL
- const int WAGE_SAVEDGAME_DESCRIPTION_LEN = 127;
- char description[WAGE_SAVEDGAME_DESCRIPTION_LEN + 1];
- data->read(description, 128);
- if (description[WAGE_SAVEDGAME_DESCRIPTION_LEN] != 0) {
- warning("Description's last byte is not '\0'");
- description[WAGE_SAVEDGAME_DESCRIPTION_LEN] = 0;
+ // update scene chrs
+ for (uint32 i = 0; i < orderedChrs.size(); ++i) {
+ Chr *chr = orderedChrs[i];
+ Scene *scene = chr->_currentScene;
+ scene->_chrs.push_back(chr);
+ if (chr != player) {
+ wearObjs(chr);
}
+ }
- int version = data->readByte();
- if (version != SAVEGAME_CURRENT_VERSION) {
- warning("Reading version %d while current is %d", version, SAVEGAME_CURRENT_VERSION);
+ // move all worn helmets, shields, chest armors and spiritual
+ // armors to player
+ for (int type = 0; type < Chr::ChrArmorType::NUMBER_OF_ARMOR_TYPES; ++type) {
+ Obj *armor;
+
+ if (type == Chr::ChrArmorType::HEAD_ARMOR)
+ armor = getObjByOffset(helmetOffset, objsHexOffset);
+ else if (type == Chr::ChrArmorType::SHIELD_ARMOR)
+ armor = getObjByOffset(shieldOffset, objsHexOffset);
+ else if (type == Chr::ChrArmorType::BODY_ARMOR)
+ armor = getObjByOffset(armorOffset, objsHexOffset);
+ else
+ armor = getObjByOffset(spiritualArmorOffset, objsHexOffset);
+
+ if (armor != nullptr) {
+ _world->move(armor, player);
+ player->_armor[type] = armor;
}
+ }
+
+ //TODO: make sure that armor in the inventory gets put on if we are wearing it
+
+ _loopCount = loopNum;
- // Thumbnail
- Graphics::loadThumbnail(*data);
+ // let the engine know if there is a npc in the current scene
+ if (presCharOffset != 0xffff) {
+ _monster = getChrByOffset(presCharOffset, chrsHexOffset);
}
+ // java engine calls clearOutput(); here
+ // processTurn("look", NULL); called in Wage right after this loadGame()
+
+ // TODO: as you may see, aim, opponentAim or runCharOffset are not used anywhere
+ // I'm fixing the first two, as those are clearly not even mentioned anywhere
+ // the runCharOffset is mentioned up there as "not implemented case"
+ _aim = aim;
+ _opponentAim = opponentAim;
+
delete data;
return 0;
}
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index f1ed5d4..f057da2 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -130,10 +130,9 @@ Common::Error WageEngine::run() {
if (ConfMan.hasKey("save_slot")) {
int saveSlot = ConfMan.getInt("save_slot");
loadGame(saveSlot);
- } else {
- Common::String input("look");
- processTurn(&input, NULL);
}
+ Common::String input("look");
+ processTurn(&input, NULL);
_temporarilyHidden = false;
_shouldQuit = false;
@@ -252,6 +251,8 @@ bool WageEngine::saveDialog() {
void WageEngine::saveGame() {
warning("STUB: saveGame()");
+ Common::String fileName = getSavegameFilename(1), desc = "test save #1";
+ saveGame(fileName, desc);
}
void WageEngine::performInitialSetup() {
@@ -313,6 +314,11 @@ void WageEngine::performInitialSetup() {
}
}
+void WageEngine::wearObjs(Chr* chr) {
+ if (chr != nullptr)
+ chr->wearObjs();
+}
+
void WageEngine::doClose() {
warning("STUB: doClose()");
}
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index 5507ed9..718f5e2 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -212,6 +212,11 @@ public:
private:
int getSceneIndex(Scene *scene) const;
+ Obj *getObjByOffset(int offset, int objBaseOffset) const;
+ Chr *getChrById(int resId) const;
+ Chr *getChrByOffset(int offset, int chrBaseOffset) const;
+ Scene *getSceneById(int id) const;
+ Scene *getSceneByOffset(int offset) const;
int saveGame(const Common::String &fileName, const Common::String &descriptionString);
int loadGame(int slotId);
Common::String getSavegameFilename(int16 slotId) const;
Commit: a80547b206b179f5d5c04cac58cc2b60251a044a
https://github.com/scummvm/scummvm/commit/a80547b206b179f5d5c04cac58cc2b60251a044a
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-28T21:47:52+06:00
Commit Message:
WAGE: Refresh menus on load
Changed paths:
engines/wage/wage.cpp
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index f057da2..fe10b1a 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -130,6 +130,8 @@ Common::Error WageEngine::run() {
if (ConfMan.hasKey("save_slot")) {
int saveSlot = ConfMan.getInt("save_slot");
loadGame(saveSlot);
+ _gui->regenCommandsMenu();
+ _gui->regenWeaponsMenu();
}
Common::String input("look");
processTurn(&input, NULL);
Commit: faed7c79730f13d98f7b68794293891404013b58
https://github.com/scummvm/scummvm/commit/faed7c79730f13d98f7b68794293891404013b58
Author: Alexander Tkachev (alexander at tkachov.ru)
Date: 2016-07-29T11:35:36+06:00
Commit Message:
WAGE: Fix Chr::ChrArmorType unknown identifier
It should've been `Chr` instead.
Changed paths:
engines/wage/saveload.cpp
diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp
index 654812a..4889add 100644
--- a/engines/wage/saveload.cpp
+++ b/engines/wage/saveload.cpp
@@ -212,16 +212,16 @@ int WageEngine::saveGame(const Common::String &fileName, const Common::String &d
out->writeSint32LE(GET_HEX_SCENE_OFFSET(player->_currentScene)); //getCurSceneHexOffset()
// wearing a helmet?
- out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::HEAD_ARMOR])); //helmetIndex
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::HEAD_ARMOR])); //helmetIndex
// holding a shield?
- out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::SHIELD_ARMOR])); //shieldIndex
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::SHIELD_ARMOR])); //shieldIndex
// wearing chest armor?
- out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::BODY_ARMOR])); //chestArmIndex
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::BODY_ARMOR])); //chestArmIndex
// wearing spiritual armor?
- out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::ChrArmorType::MAGIC_ARMOR])); //sprtArmIndex
+ out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::MAGIC_ARMOR])); //sprtArmIndex
// TODO:
out->writeSint16LE(0xffff); // ???? - always FFFF
@@ -675,14 +675,14 @@ int WageEngine::loadGame(int slotId) {
// move all worn helmets, shields, chest armors and spiritual
// armors to player
- for (int type = 0; type < Chr::ChrArmorType::NUMBER_OF_ARMOR_TYPES; ++type) {
+ for (int type = 0; type < Chr::NUMBER_OF_ARMOR_TYPES; ++type) {
Obj *armor;
- if (type == Chr::ChrArmorType::HEAD_ARMOR)
+ if (type == Chr::HEAD_ARMOR)
armor = getObjByOffset(helmetOffset, objsHexOffset);
- else if (type == Chr::ChrArmorType::SHIELD_ARMOR)
+ else if (type == Chr::SHIELD_ARMOR)
armor = getObjByOffset(shieldOffset, objsHexOffset);
- else if (type == Chr::ChrArmorType::BODY_ARMOR)
+ else if (type == Chr::BODY_ARMOR)
armor = getObjByOffset(armorOffset, objsHexOffset);
else
armor = getObjByOffset(spiritualArmorOffset, objsHexOffset);
Commit: b9198d37f7ea397c338d6c0afec05840bdf21403
https://github.com/scummvm/scummvm/commit/b9198d37f7ea397c338d6c0afec05840bdf21403
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-07-29T10:09:13+03:00
Commit Message:
Merge pull request #793 from Tkachov/wage
WAGE: Add save/load code
Changed paths:
A engines/wage/saveload.cpp
engines/wage/entities.cpp
engines/wage/entities.h
engines/wage/module.mk
engines/wage/wage.cpp
engines/wage/wage.h
engines/wage/world.cpp
engines/wage/world.h
More information about the Scummvm-git-logs
mailing list