aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2015-01-05 08:11:16 -0500
committerPaul Gilbert2015-01-05 08:11:16 -0500
commitce96094c9bc54266c9742364e656c97446a6ecaf (patch)
tree618ff200be5941a57b5aa16554ecdfe05df63055 /engines
parentf9316bf14107c3ac46bd8bb53da9665c3652c381 (diff)
downloadscummvm-rg350-ce96094c9bc54266c9742364e656c97446a6ecaf.tar.gz
scummvm-rg350-ce96094c9bc54266c9742364e656c97446a6ecaf.tar.bz2
scummvm-rg350-ce96094c9bc54266c9742364e656c97446a6ecaf.zip
XEEN: In progress implementing map loading
Diffstat (limited to 'engines')
-rw-r--r--engines/xeen/dialogs.cpp25
-rw-r--r--engines/xeen/dialogs.h7
-rw-r--r--engines/xeen/dialogs_error.cpp77
-rw-r--r--engines/xeen/dialogs_error.h50
-rw-r--r--engines/xeen/events.cpp16
-rw-r--r--engines/xeen/events.h19
-rw-r--r--engines/xeen/files.cpp5
-rw-r--r--engines/xeen/files.h6
-rw-r--r--engines/xeen/interface.cpp221
-rw-r--r--engines/xeen/interface.h18
-rw-r--r--engines/xeen/map.cpp824
-rw-r--r--engines/xeen/map.h264
-rw-r--r--engines/xeen/module.mk2
-rw-r--r--engines/xeen/party.cpp12
-rw-r--r--engines/xeen/party.h11
-rw-r--r--engines/xeen/resources.cpp24
-rw-r--r--engines/xeen/resources.h10
-rw-r--r--engines/xeen/saves.cpp8
-rw-r--r--engines/xeen/saves.h4
-rw-r--r--engines/xeen/screen.cpp4
-rw-r--r--engines/xeen/screen.h2
-rw-r--r--engines/xeen/sprites.cpp8
-rw-r--r--engines/xeen/sprites.h2
-rw-r--r--engines/xeen/xeen.cpp35
-rw-r--r--engines/xeen/xeen.h13
25 files changed, 1591 insertions, 76 deletions
diff --git a/engines/xeen/dialogs.cpp b/engines/xeen/dialogs.cpp
index 70a22d16ee..8e8e7521cb 100644
--- a/engines/xeen/dialogs.cpp
+++ b/engines/xeen/dialogs.cpp
@@ -50,19 +50,19 @@ void ButtonContainer::addButton(const Common::Rect &bounds, int val, SpriteResou
_buttons.push_back(UIButton(bounds, val, sprites, draw));
}
-void ButtonContainer::checkEvents(XeenEngine *vm) {
+bool ButtonContainer::checkEvents(XeenEngine *vm) {
EventsManager &events = *vm->_events;
- events.pollEventsAndWait();
if (events._leftButton) {
// Check whether any button is selected
- events.debounceMouse();
Common::Point pt = events._mousePos;
for (uint i = 0; i < _buttons.size(); ++i) {
if (_buttons[i]._bounds.contains(pt)) {
+ events.debounceMouse();
+
_buttonValue = _buttons[i]._value;
- return;
+ return true;
}
}
} else if (events.isKeyPending()) {
@@ -70,9 +70,11 @@ void ButtonContainer::checkEvents(XeenEngine *vm) {
events.getKey(keyState);
if (keyState.ascii >= 32 && keyState.ascii <= 127) {
_buttonValue = keyState.ascii;
- return;
+ return true;
}
}
+
+ return false;
}
@@ -193,10 +195,10 @@ void ButtonContainer::drawButtons(XSurface *surface) {
}
}
-
/*------------------------------------------------------------------------*/
void SettingsBaseDialog::showContents(SpriteResource &title1, bool waitFlag) {
+ _vm->_events->pollEventsAndWait();
checkEvents(_vm);
}
@@ -231,4 +233,15 @@ void CreditsScreen::execute() {
doScroll(_vm, true, false);
}
+/*------------------------------------------------------------------------*/
+
+void PleaseWait::show(XeenEngine *vm) {
+ if (vm->_mode != MODE_0) {
+ Window &w = vm->_screen->_windows[9];
+ w.open();
+ w.writeString(PLEASE_WAIT);
+ w.update();
+ }
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/dialogs.h b/engines/xeen/dialogs.h
index 61ae73473d..987df6b2f1 100644
--- a/engines/xeen/dialogs.h
+++ b/engines/xeen/dialogs.h
@@ -54,7 +54,7 @@ protected:
void doScroll(XeenEngine *vm, bool drawFlag, bool doFade);
- void checkEvents(XeenEngine *vm);
+ bool checkEvents(XeenEngine *vm);
void drawButtons(XSurface *surface);
public:
@@ -89,6 +89,11 @@ public:
static void show(XeenEngine *vm);
};
+class PleaseWait {
+public:
+ static void show(XeenEngine *vm);
+};
+
} // End of namespace Xeen
#endif /* XEEN_DIALOGS_H */
diff --git a/engines/xeen/dialogs_error.cpp b/engines/xeen/dialogs_error.cpp
new file mode 100644
index 0000000000..c0c072386d
--- /dev/null
+++ b/engines/xeen/dialogs_error.cpp
@@ -0,0 +1,77 @@
+/* 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/scummsys.h"
+#include "xeen/dialogs_error.h"
+#include "xeen/events.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+void ErrorScroll::show(XeenEngine *vm, const Common::String &msg, ErrorWaitType waitType) {
+ ErrorScroll *dlg = new ErrorScroll(vm);
+ dlg->execute(msg, waitType);
+ delete dlg;
+}
+
+void ErrorScroll::execute(const Common::String &msg, ErrorWaitType waitType) {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ Window &w = screen._windows[6];
+
+ Common::String s = Common::String::format("\x03c\v010\t000%s", msg);
+ w.open();
+ w.writeString(s);
+ w.update();
+
+ switch (waitType) {
+ case WT_FREEZE_WAIT:
+ while (!_vm->shouldQuit() && !events.isKeyPending())
+ events.pollEventsAndWait();
+
+ events.clearEvents();
+ break;
+ case WT_3:
+ if (w._enabled || _vm->_mode == MODE_17) {
+ warning("TODO: sub_26D8F");
+ break;
+ }
+ // Deliberate fall-through
+ case WT_NONFREEZED_WAIT:
+ do {
+ events.updateGameCounter();
+ _vm->_interface->draw3d(true);
+
+ events.wait(1, true);
+ if (checkEvents(_vm))
+ break;
+ } while (!_vm->shouldQuit() && !_buttonValue);
+ break;
+ case WT_2:
+ warning("TODO: sub_26D8F");
+ break;
+ default:
+ break;
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_error.h b/engines/xeen/dialogs_error.h
new file mode 100644
index 0000000000..03a6f16cf2
--- /dev/null
+++ b/engines/xeen/dialogs_error.h
@@ -0,0 +1,50 @@
+/* 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.
+ *
+ */
+
+#ifndef XEEN_DIALOGS_ERROR_H
+#define XEEN_DIALOGS_ERROR_H
+
+#include "common/array.h"
+#include "common/stack.h"
+#include "common/rect.h"
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+enum ErrorWaitType { WT_FREEZE_WAIT = 0, WT_NONFREEZED_WAIT = 1,
+ WT_2 = 2, WT_3 = 3};
+
+class ErrorScroll: public ButtonContainer {
+private:
+ XeenEngine *_vm;
+
+ ErrorScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+ void execute(const Common::String &msg, ErrorWaitType waitType);
+public:
+ static void show(XeenEngine *vm, const Common::String &msg,
+ ErrorWaitType waitType = WT_FREEZE_WAIT);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_ERROR_H */
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 285005af98..e0c3b26dc6 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -39,6 +39,7 @@ EventsManager::EventsManager(XeenEngine *vm) : _vm(vm),
_priorGameCounterTime(0), _keyCode(Common::KEYCODE_INVALID),
_leftButton(false), _rightButton(false),
_sprites("mouse.icn") {
+ Common::fill(&_gameCounters[0], &_gameCounters[6], 0);
}
/**
@@ -157,21 +158,6 @@ bool EventsManager::isKeyMousePressed() {
return result;
}
-/**
- * Updates the game counter to match the current frame counter
- */
-void EventsManager::updateGameCounter() {
- _gameCounter = _frameCounter;
-}
-
-/**
- * Returns the number of frames elapsed since the last call to
- * updateGameCounter()
- */
-uint32 EventsManager::timeElapsed() {
- return _frameCounter - _gameCounter;
-}
-
bool EventsManager::wait(uint numFrames, bool interruptable) {
while (!_vm->shouldQuit() && timeElapsed() < numFrames) {
pollEventsAndWait();
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 7a6a65f4fb..1705bb43d3 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -39,6 +39,7 @@ private:
uint32 _frameCounter;
uint32 _priorFrameCounterTime;
uint32 _gameCounter;
+ uint32 _gameCounters[6];
uint32 _priorGameCounterTime;
Common::KeyCode _keyCode;
SpriteResource _sprites;
@@ -52,8 +53,6 @@ public:
~EventsManager();
- uint32 getFrameCounter() { return _frameCounter; }
-
void setCursor(int cursorId);
void showCursor();
@@ -76,9 +75,19 @@ public:
bool isKeyMousePressed();
- void updateGameCounter();
-
- uint32 timeElapsed();
+ void updateGameCounter() { _gameCounter = _frameCounter; }
+ void timeMark1() { _gameCounters[1] = _frameCounter; }
+ void timeMark2() { _gameCounters[2] = _frameCounter; }
+ void timeMark3() { _gameCounters[3] = _frameCounter; }
+ void timeMark4() { _gameCounters[4] = _frameCounter; }
+ void timeMark5() { _gameCounters[5] = _frameCounter; }
+
+ uint32 timeElapsed() const { return _frameCounter - _gameCounter; }
+ uint32 timeElapsed1() const { return _frameCounter - _gameCounters[1]; }
+ uint32 timeElapsed2() const { return _frameCounter - _gameCounters[2]; }
+ uint32 timeElapsed3() const { return _frameCounter - _gameCounters[3]; }
+ uint32 timeElapsed4() const { return _frameCounter - _gameCounters[4]; }
+ uint32 timeElapsed5() const { return _frameCounter - _gameCounters[5]; }
bool wait(uint numFrames, bool interruptable = false);
};
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 107cde45a1..a0ca2435a1 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -160,10 +160,11 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEn
/**
* Instantiates the resource manager
*/
-void FileManager::init(XeenEngine *vm) {
+FileManager::FileManager(XeenEngine *vm) {
Common::File f;
- if (vm->getGameID() != GType_Clouds)
+ _isDarkCc = vm->getGameID() != GType_Clouds;
+ if (_isDarkCc)
SearchMan.add("dark", new CCArchive("dark.cc"));
SearchMan.add("xeen", new CCArchive("xeen.cc"));
SearchMan.add("intro", new CCArchive("intro.cc"));
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 8a028a95c7..3e38ad842c 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -38,7 +38,11 @@ class XeenEngine;
*/
class FileManager {
public:
- static void init(XeenEngine *vm);
+ bool _isDarkCc;
+public:
+ FileManager(XeenEngine *vm);
+
+ void setGameCc(bool isDarkCc) { _isDarkCc = isDarkCc; }
};
/**
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 3a07cecec6..08128e54f0 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -21,6 +21,7 @@
*/
#include "xeen/interface.h"
+#include "xeen/dialogs_error.h"
#include "xeen/resources.h"
#include "xeen/xeen.h"
@@ -41,16 +42,18 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), _vm(vm) {
_buttonsLoaded = false;
_hiliteChar = -1;
Common::fill(&_combatCharIds[0], &_combatCharIds[8], 0);
+ _intrIndex1 = 0;
_faceDrawStructs[0] = DrawStruct(nullptr, 0, 0, 0);
_faceDrawStructs[1] = DrawStruct(nullptr, 0, 101, 0);
_faceDrawStructs[2] = DrawStruct(nullptr, 0, 0, 43);
_faceDrawStructs[3] = DrawStruct(nullptr, 0, 101, 43);
-
- loadSprites();
}
-void Interface::loadSprites() {
+void Interface::manageCharacters(bool soundPlayed) {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ bool flag = false;
_globalSprites.load("global.icn");
_borderSprites.load("border.icn");
_spellFxSprites.load("spellfx.icn");
@@ -58,21 +61,21 @@ void Interface::loadSprites() {
_blessSprites.load("bless.icn");
_restoreSprites.load("restorex.icn");
_hpSprites.load("hpbars.icn");
-}
-
-void Interface::setup(bool soundPlayed) {
- Screen &screen = *_vm->_screen;
- SpriteResource uiSprites("inn.icn");
+ _uiSprites.load("inn.icn");
+start:
// Get mappings to the active characters in the party
_vm->_party._activeParty.resize(_vm->_party._partyCount);
for (int i = 0; i < _vm->_party._partyCount; ++i) {
- _vm->_party._activeParty[i] = &_vm->_roster[_vm->_party._partyMembers[i]];
+ _vm->_party._activeParty[i] = _vm->_roster[_vm->_party._partyMembers[i]];
}
_isEarlyGame = _vm->_party._minutes >= 300;
- if (_vm->_party._mazeId == 0) {
+ if (_vm->_party._mazeId != 0) {
+ _vm->_mode = MODE_0;
+ _buttonsLoaded = true;
+ } else {
if (!soundPlayed) {
warning("TODO: loadSound?");
}
@@ -100,25 +103,156 @@ void Interface::setup(bool soundPlayed) {
// Add in buttons for the UI
_interfaceText = "";
_buttonsLoaded = true;
- addButton(Common::Rect(16, 100, 40, 120), 242, &uiSprites, true);
- addButton(Common::Rect(52, 100, 76, 120), 243, &uiSprites, true);
- addButton(Common::Rect(87, 100, 111, 120), 68, &uiSprites, true);
- addButton(Common::Rect(122, 100, 146, 120), 82, &uiSprites, true);
- addButton(Common::Rect(157, 100, 181, 120), 67, &uiSprites, true);
- addButton(Common::Rect(192, 100, 216, 120), 88, &uiSprites, true);
- addButton(Common::Rect(), 27, &uiSprites, false);
- addButton(Common::Rect(16, 16, 48, 48), 49, &uiSprites, false);
- addButton(Common::Rect(117, 16, 139, 48), 50, &uiSprites, false);
- addButton(Common::Rect(16, 59, 48, 81), 51, &uiSprites, false);
- addButton(Common::Rect(117, 59, 149, 81), 52, &uiSprites, false);
+ addButton(Common::Rect(16, 100, 40, 120), 242, &_uiSprites, true);
+ addButton(Common::Rect(52, 100, 76, 120), 243, &_uiSprites, true);
+ addButton(Common::Rect(87, 100, 111, 120), 68, &_uiSprites, true);
+ addButton(Common::Rect(122, 100, 146, 120), 82, &_uiSprites, true);
+ addButton(Common::Rect(157, 100, 181, 120), 67, &_uiSprites, true);
+ addButton(Common::Rect(192, 100, 216, 120), 88, &_uiSprites, true);
+ addButton(Common::Rect(), 27, &_uiSprites, false);
+ addButton(Common::Rect(16, 16, 48, 48), 49, &_uiSprites, false);
+ addButton(Common::Rect(117, 16, 139, 48), 50, &_uiSprites, false);
+ addButton(Common::Rect(16, 59, 48, 81), 51, &_uiSprites, false);
+ addButton(Common::Rect(117, 59, 149, 81), 52, &_uiSprites, false);
setupBackground();
- screen._windows[11].open();
- setupFaces(0, xeenSideChars, 0);
- screen._windows[11].writeString(_interfaceText);
+ Window &w = screen._windows[11];
+ w.open();
+ setupFaces(0, xeenSideChars, false);
+ w.writeString(_interfaceText);
+ w.drawList(&_faceDrawStructs[0], 4);
+
+ _uiSprites.draw(w, 0, Common::Point(16, 100));
+ _uiSprites.draw(w, 2, Common::Point(52, 100));
+ _uiSprites.draw(w, 4, Common::Point(87, 100));
+ _uiSprites.draw(w, 6, Common::Point(122, 100));
+ _uiSprites.draw(w, 8, Common::Point(157, 100));
+ _uiSprites.draw(w, 10, Common::Point(192, 100));
+
+ screen.loadPalette("mm4.pal");
+
+ if (flag) {
+ screen._windows[0].update();
+ events.setCursor(0);
+ screen.fadeIn(4);
+ } else {
+ if (_vm->getGameID() == GType_DarkSide) {
+ screen.fadeOut(4);
+ screen._windows[0].update();
+ }
+
+ doScroll(_vm, false, false);
+ events.setCursor(0);
+
+ if (_vm->getGameID() == GType_DarkSide) {
+ screen.fadeIn(4);
+ }
+ }
// TODO
+ bool breakFlag = false;
+ while (!_vm->shouldQuit() && !breakFlag) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_SPACE:
+ case Common::KEYCODE_e:
+ case Common::KEYCODE_x:
+ if (_vm->_party._partyCount == 0) {
+ ErrorScroll::show(_vm, NO_ONE_TO_ADVENTURE_WITH);
+ } else {
+ if (_vm->_mode != MODE_0) {
+ for (_intrIndex1 = 4; _intrIndex1 >= 0; --_intrIndex1) {
+ events.updateGameCounter();
+ drawViewBackground(_intrIndex1);
+ w.update();
+
+ while (events.timeElapsed() < 1)
+ events.pollEventsAndWait();
+ }
+ }
+
+ w.close();
+ _vm->_party._realPartyCount = _vm->_party._partyCount;
+ _vm->_party._mazeId = _vm->_party._priorMazeId;
+
+ _vm->_party.copyPartyToRoster(_vm->_roster);
+ _vm->_saves->writeCharFile();
+ breakFlag = true;
+ break;
+ }
+ break;
+ case Common::KEYCODE_1:
+ break;
+ case Common::KEYCODE_2:
+ break;
+ case Common::KEYCODE_3:
+ break;
+ case Common::KEYCODE_4:
+ break;
+ case Common::KEYCODE_c:
+ if (xeenSideChars.size() == 24) {
+ ErrorScroll::show(_vm, YOUR_ROSTER_IS_FULL);
+ } else {
+ screen.fadeOut(4);
+ w.close();
+ addCharacterToRoster();
+ _vm->_saves->writeCharFile();
+ screen.fadeOut(4);
+ flag = true;
+ _buttonsLoaded = true;
+ goto start;
+ }
+ break;
+ case Common::KEYCODE_d:
+ break;
+ case Common::KEYCODE_r:
+ if (_vm->_party._partyCount > 0) {
+ // TODO
+ }
+ break;
+ case 201:
+ // TODO
+ break;
+ case 202:
+ // TODO
+ break;
+ case 203:
+ // TODO
+ break;
+ case 204:
+ // TODO
+ break;
+ case 205:
+ // TODO
+ break;
+ case 206:
+ // TODO
+ break;
+ case 242:
+ // TODO
+ break;
+ case 243:
+ // TODO
+ break;
+ default:
+ break;
+ }
+ }
}
+
+ for (int i = 0; i < TOTAL_CHARACTERS; ++i)
+ _charFaces[i].clear();
+ _globalSprites.clear();
+ _borderSprites.clear();
+ _spellFxSprites.clear();
+ _fecpSprites.clear();
+ _blessSprites.clear();
+ _restoreSprites.clear();
+ _hpSprites.clear();
+ _uiSprites.clear();
}
void Interface::loadCharIcons(int numChars) {
@@ -244,7 +378,7 @@ void Interface::assembleBorder() {
screen._windows[12].frame();
}
-void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3) {
+void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag) {
Common::String playerNames[4];
Common::String playerRaces[4];
Common::String playerSex[4];
@@ -271,7 +405,7 @@ void Interface::setupFaces(int charIndex, Common::Array<int> xeenSideChars, int
playerClass[posIndex] = CLASS_NAMES[ps._class];
}
- charIconsPrint(v3);
+ charIconsPrint(updateFlag);
// Set up the sprite set to use for each face
charId = xeenSideChars[charIndex];
@@ -300,7 +434,7 @@ void Interface::charIconsPrint(bool updateFlag) {
for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount :
_vm->_party._partyCount); ++idx) {
int charIndex = stateFlag ? _combatCharIds[idx] : idx;
- PlayerStruct &ps = *_vm->_party._activeParty[charIndex];
+ PlayerStruct &ps = _vm->_party._activeParty[charIndex];
Condition charCondition = ps.findCondition();
int charFrame = FACE_CONDITION_FRAMES[charCondition];
@@ -316,7 +450,7 @@ void Interface::charIconsPrint(bool updateFlag) {
for (int idx = 0; idx < (stateFlag ? _vm->_party._combatPartyCount :
_vm->_party._partyCount); ++idx) {
int charIndex = stateFlag ? _combatCharIds[idx] : idx;
- PlayerStruct &ps = *_vm->_party._activeParty[charIndex];
+ PlayerStruct &ps = _vm->_party._activeParty[charIndex];
// Draw the Hp bar
int maxHp = ps.getMaxHp();
@@ -343,4 +477,35 @@ void Interface::charIconsPrint(bool updateFlag) {
screen._windows[33].update();
}
+void Interface::drawViewBackground(int bgType) {
+ if (bgType >= 4)
+ return;
+
+ if (bgType == 0) {
+ // Totally black background
+ _vm->_screen->fillRect(Common::Rect(8, 8, 224, 140), 0);
+ } else {
+ const byte *lookup = BACKGROUND_XLAT + bgType;
+ for (int yp = 8; yp < 140; ++yp) {
+ byte *destP = (byte *)_vm->_screen->getBasePtr(8, yp);
+ for (int xp = 8; xp < 224; ++xp, ++destP)
+ *destP = lookup[*destP];
+ }
+ }
+}
+
+void Interface::addCharacterToRoster() {
+ error("TODO");
+}
+
+void Interface::draw3d(bool flag) {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+
+ if (!screen._windows[11]._enabled)
+ return;
+
+ warning("TODO");
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index 3ceb08239e..1ed7afe628 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -43,6 +43,7 @@ private:
SpriteResource _blessSprites;
SpriteResource _restoreSprites;
SpriteResource _hpSprites;
+ SpriteResource _uiSprites;
SpriteResource _charFaces[TOTAL_CHARACTERS];
SpriteResource *_partyFaces[MAX_ACTIVE_PARTY];
DrawStruct _faceDrawStructs[4];
@@ -61,22 +62,27 @@ private:
bool _buttonsLoaded;
Common::String _interfaceText;
int _hiliteChar;
-
- void loadSprites();
-
- void loadCharIcons(int numChars);
+ int _intrIndex1;
void assembleBorder();
void setupBackground();
- void setupFaces(int charIndex, Common::Array<int> xeenSideChars, int v3);
+ void setupFaces(int charIndex, Common::Array<int> xeenSideChars, bool updateFlag);
void charIconsPrint(bool updateFlag);
+
+ void drawViewBackground(int bgType);
+
+ void addCharacterToRoster();
public:
Interface(XeenEngine *vm);
- void setup(bool soundPlayed);
+ void manageCharacters(bool soundPlayed);
+
+ void loadCharIcons(int numChars);
+
+ void draw3d(bool flag);
};
} // End of namespace Xeen
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
new file mode 100644
index 0000000000..d797179e15
--- /dev/null
+++ b/engines/xeen/map.cpp
@@ -0,0 +1,824 @@
+/* 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/serializer.h"
+#include "xeen/map.h"
+#include "xeen/resources.h"
+#include "xeen/saves.h"
+#include "xeen/screen.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+MonsterStruct::MonsterStruct() {
+ _experience = 0;
+ _hp = 0;
+ _accuracy = 0;
+ _speed = 0;
+ _numberOfAttacks = 0;
+ _hatesClass = CLASS_KNIGHT;
+ _strikes = 0;
+ _dmgPerStrike = 0;
+ _attackType = DT_PHYSICAL;
+ _specialAttack = SA_NONE;
+ _hitChance = 0;
+ _rangeAttack = 0;
+ _monsterType = MONSTER_0;
+ _fireResistence = 0;
+ _electricityResistence = 0;
+ _coldResistence = 0;
+ _poisonResistence = 0;
+ _energyResistence = 0;
+ _magicResistence = 0;
+ _phsyicalResistence = 0;
+ _field29 = 0;
+ _gold = 0;
+ _gems = 0;
+ _itemDrop = 0;
+ _flying = 0;
+ _imageNumber = 0;
+ _loopAnimation = 0;
+ _animationEffect = 0;
+ _field32 = 0;
+}
+
+MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int accuracy,
+ int speed, int numberOfAttacks, CharacterClass hatesClass, int strikes,
+ int dmgPerStrike, DamageType attackType, SpecialAttack specialAttack,
+ int hitChance, int rangeAttack, MonsterType monsterType,
+ int fireResistence, int electricityResistence, int coldResistence,
+ int poisonResistence, int energyResistence, int magicResistence,
+ int phsyicalResistence, int field29, int gold, int gems, int itemDrop,
+ int flying, int imageNumber, int loopAnimation, int animationEffect,
+ int field32, Common::String attackVoc):
+ _name(name), _experience(experience), _hp(hp), _accuracy(accuracy),
+ _speed(speed), _numberOfAttacks(numberOfAttacks), _hatesClass(hatesClass),
+ _strikes(strikes), _dmgPerStrike(dmgPerStrike), _attackType(attackType),
+ _specialAttack(specialAttack), _hitChance(hitChance), _rangeAttack(rangeAttack),
+ _monsterType(monsterType), _fireResistence(fireResistence),
+ _electricityResistence(electricityResistence), _coldResistence(coldResistence),
+ _poisonResistence(poisonResistence), _energyResistence(energyResistence),
+ _magicResistence(magicResistence), _phsyicalResistence(phsyicalResistence),
+ _field29(field29), _gold(gold), _gems(gems), _itemDrop(itemDrop),
+ _flying(flying), _imageNumber(imageNumber), _loopAnimation(loopAnimation),
+ _animationEffect(animationEffect), _field32(field32), _attackVoc(attackVoc) {
+}
+
+
+void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
+ _experience = s.readByte();
+ _hp = s.readByte();
+ _accuracy = s.readByte();
+ _speed = s.readByte();
+ _numberOfAttacks = s.readByte();
+ _hatesClass = CLASS_KNIGHT;
+ _strikes = s.readByte();
+ _dmgPerStrike = s.readByte();
+ _attackType = (DamageType)s.readByte();
+ _specialAttack = (SpecialAttack)s.readByte();
+ _hitChance = s.readByte();
+ _rangeAttack = s.readByte();
+ _monsterType = (MonsterType)s.readByte();
+ _fireResistence = s.readByte();
+ _electricityResistence = s.readByte();
+ _coldResistence = s.readByte();
+ _poisonResistence = s.readByte();
+ _energyResistence = s.readByte();
+ _magicResistence = s.readByte();
+ _phsyicalResistence = s.readByte();
+ _field29 = s.readByte();
+ _gold = s.readByte();
+ _gems = s.readByte();
+ _itemDrop = s.readByte();
+ _flying = s.readByte();
+ _imageNumber = s.readByte();
+ _loopAnimation = s.readByte();
+ _animationEffect = s.readByte();
+ _field32 = s.readByte();
+
+ char attackVoc[9];
+ s.read(attackVoc, 9);
+ attackVoc[8] = '\0';
+ _attackVoc = Common::String(attackVoc);
+}
+
+MonsterData::MonsterData() {
+ push_back(MonsterStruct("", 0, 0, 0, 0, 0, CLASS_KNIGHT, 1, 1, DT_PHYSICAL,
+ SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 100, "Slime"));
+ push_back(MonsterStruct("Whirlwind", 250000, 1000, 10, 250, 1, CLASS_15, 5,
+ 100, DT_PHYSICAL, SA_CONFUSE, 250, 0, MONSTER_0, 100,
+ 100, 100, 100, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 176,
+ "airmon"));
+ push_back(MonsterStruct("Annihilator", 1000000, 1500, 40, 200, 12, CLASS_16, 5,
+ 50, DT_ENERGY, SA_NONE, 1, 1, MONSTER_0, 80, 80, 100,
+ 100, 0, 0, 80, 0, 0, 0, 0, 0, 2, 0, 0, 102, "alien1"));
+ push_back(MonsterStruct("Autobot", 1000000, 2500, 100, 200, 2, CLASS_16, 5,
+ 100, DT_ENERGY, SA_NONE, 1, 0, MONSTER_0, 50, 50, 100,
+ 100, 0, 0, 50, 0, 0, 0, 0, 1, 3, 0, 0, 101, "alien2"));
+ push_back(MonsterStruct("Sewer Stalker", 50000, 250, 30, 25, 1, CLASS_16, 3,
+ 100, DT_PHYSICAL, SA_NONE, 50, 0, MONSTER_ANIMAL, 0,
+ 0, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 113,
+ "iguana"));
+ push_back(MonsterStruct("Armadillo", 60000, 800, 50, 15, 1, CLASS_16, 100, 6,
+ DT_PHYSICAL, SA_BREAKWEAPON, 60, 0, MONSTER_ANIMAL,
+ 50, 0, 80, 80, 50, 0, 50, 0, 0, 0, 0, 0, 5, 1, 0, 113,
+ "unnh"));
+ push_back(MonsterStruct("Barbarian", 5000, 50, 5, 40, 3, CLASS_SORCERER, 1, 20,
+ DT_PHYSICAL, SA_NONE, 20, 1, MONSTER_HUMANOID, 0, 0,
+ 0, 0, 0, 0, 0, 0, 100, 0, 3, 0, 6, 0, 0, 100,
+ "barbarch"));
+ push_back(MonsterStruct("Electrapede", 10000, 200, 10, 50, 1, CLASS_PALADIN,
+ 50, 1, DT_ELECTRICAL, SA_PARALYZE, 1, 0,
+ MONSTER_INSECT, 50, 100, 50, 50, 50, 0, 0, 0, 0, 0, 0,
+ 0, 7, 1, 0, 107, "centi"));
+ push_back(MonsterStruct("Cleric of Mok", 30000, 125, 10, 40, 1, CLASS_CLERIC,
+ 250, 1, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID,
+ 10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, 0, 8, 0, 0,
+ 117, "cleric"));
+ push_back(MonsterStruct("Mok Heretic", 50000, 150, 12, 50, 1, CLASS_CLERIC,
+ 500, 1, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50,
+ 20, 20, 20, 30, 0, 0, 0, 25, 4, 0, 8, 0, 0, 117,
+ "cleric"));
+ push_back(MonsterStruct("Mantis Ant", 40000, 300, 30, 40, 2, CLASS_16, 2, 100,
+ DT_PHYSICAL, SA_POISON, 30, 0, MONSTER_INSECT, 0, 0,
+ 0, 100, 0, 0, 30, 0, 0, 0, 0, 0, 10, 0, 0, 104,
+ "spell001"));
+ push_back(MonsterStruct("Cloud Dragon", 500000, 2000, 40, 150, 1, CLASS_15,
+ 600, 1, DT_COLD, SA_NONE, 1, 1, MONSTER_DRAGON, 0, 50,
+ 100, 100, 50, 25, 50, 0, 0, 10, 0, 0, 11, 0, 0, 140,
+ "tiger1"));
+ push_back(MonsterStruct("Phase Dragon", 2000000, 4000, 80, 200, 1, CLASS_15,
+ 750, 1, DT_COLD, SA_NONE, 1, 1, MONSTER_DRAGON, 0, 50,
+ 100, 100, 80, 50, 50, 0, 0, 20, 0, 0, 11, 0, 10, 140,
+ "Begger"));
+ push_back(MonsterStruct("Green Dragon", 500000, 2500, 50, 150, 1, CLASS_15,
+ 500, 1, DT_FIRE, SA_NONE, 1, 1, MONSTER_DRAGON, 100,
+ 50, 0, 100, 50, 25, 50, 0, 0, 10, 0, 0, 13, 0, 0, 140,
+ "tiger1"));
+ push_back(MonsterStruct("Energy Dragon", 2000000, 5000, 100, 250, 1, CLASS_15,
+ 1000, 1, DT_ENERGY, SA_NONE, 1, 1, MONSTER_DRAGON, 80,
+ 80, 60, 100, 100, 30, 50, 0, 0, 20, 0, 0, 13, 0, 7,
+ 140, "begger"));
+ push_back(MonsterStruct("Dragon Mummy", 2000000, 3000, 30, 100, 1,
+ CLASS_CLERIC, 2000, 2, DT_PHYSICAL, SA_DISEASE, 200,
+ 0, MONSTER_DRAGON, 0, 80, 100, 100, 0, 10, 90, 0, 0, 0,
+ 0, 0, 15, 0, 0, 140, "dragmum"));
+ push_back(MonsterStruct("Scraps", 2000000, 3000, 30, 100, 1, CLASS_16, 2000, 2,
+ DT_PHYSICAL, SA_NONE, 200, 0, MONSTER_DRAGON, 0, 80,
+ 100, 100, 0, 10, 90, 0, 0, 0, 0, 0, 15, 0, 0, 140,
+ "dragmum"));
+ push_back(MonsterStruct("Earth Blaster", 250000, 1000, 10, 100, 1, CLASS_15, 5,
+ 100, DT_PHYSICAL, SA_NONE, 200, 0, MONSTER_0, 100, 90,
+ 90, 100, 0, 0, 90, 0, 0, 0, 0, 0, 17, 0, 0, 100,
+ "earthmon"));
+ push_back(MonsterStruct("Beholder Bat", 10000, 75, 15, 80, 1, CLASS_15, 5, 5,
+ DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 18, 0, 0, 120, "eyeball"));
+ push_back(MonsterStruct("Fire Blower", 250000, 1000, 20, 60, 1, CLASS_15, 5,
+ 100, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0,
+ 100, 50, 0, 50, 0, 0, 0, 0, 0, 19, 0, 0, 110, "fire"));
+ push_back(MonsterStruct("Hell Hornet", 50000, 250, 30, 50, 2, CLASS_DRUID, 2,
+ 250, DT_POISON, SA_WEAKEN, 1, 0, MONSTER_INSECT, 50,
+ 50, 50, 100, 50, 0, 50, 0, 0, 0, 0, 1, 20, 0, 0, 123,
+ "insect"));
+ push_back(MonsterStruct("Gargoyle", 30000, 150, 35, 30, 2, CLASS_16, 5, 50,
+ DT_PHYSICAL, SA_NONE, 60, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 20, 0, 0, 0, 0, 0, 0, 21, 0, 10, 100, "gargrwl"));
+ push_back(MonsterStruct("Giant", 100000, 500, 25, 45, 2, CLASS_16, 100, 5,
+ DT_PHYSICAL, SA_UNCONSCIOUS, 100, 0, MONSTER_0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1000, 0, 5, 0, 22, 0, 0, 100,
+ "giant"));
+ push_back(MonsterStruct("Goblin", 1000, 10, 5, 30, 2, CLASS_16, 2, 6,
+ DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 131, "gremlin"));
+ push_back(MonsterStruct("Onyx Golem", 1000000, 10000, 50, 100, 1, CLASS_15, 2,
+ 250, DT_1, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100,
+ 100, 100, 100, 100, 50, 0, 0, 100, 0, 1, 24, 0, 10,
+ 100, "golem"));
+ push_back(MonsterStruct("Gremlin", 2000, 20, 7, 35, 2, CLASS_16, 2, 10,
+ DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 101, "gremlink"));
+ push_back(MonsterStruct("Gremlin Guard", 3000, 50, 10, 35, 2, CLASS_16, 6, 5,
+ DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 101, "gremlink"));
+ push_back(MonsterStruct("Griffin", 60000, 800, 35, 150, 2, CLASS_KNIGHT, 50, 6,
+ DT_PHYSICAL, SA_NONE, 150, 0, MONSTER_ANIMAL, 0, 0, 0,
+ 0, 0, 80, 0, 0, 0, 0, 0, 0, 27, 0, 0, 120, "screech"));
+ push_back(MonsterStruct("Gamma Gazer", 1000000, 5000, 60, 200, 7, CLASS_16, 10,
+ 20, DT_ENERGY, SA_NONE, 1, 0, MONSTER_0, 100, 100, 0,
+ 100, 100, 0, 60, 0, 0, 0, 0, 0, 28, 0, 0, 140, "hydra"));
+ push_back(MonsterStruct("Iguanasaurus", 100000, 2500, 20, 30, 1, CLASS_16, 10,
+ 50, DT_PHYSICAL, SA_INSANE, 150, 0, MONSTER_ANIMAL, 50,
+ 50, 50, 50, 50, 0, 20, 0, 0, 0, 0, 0, 29, 0, 0, 113,
+ "iguana"));
+ push_back(MonsterStruct("Slayer Knight", 50000, 500, 30, 50, 1, CLASS_PALADIN,
+ 2, 250, DT_PHYSICAL, SA_NONE, 100, 0, MONSTER_HUMANOID,
+ 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 5, 0, 30, 0, 0,
+ 141, "knight"));
+ push_back(MonsterStruct("Death Knight", 100000, 750, 50, 80, 2, CLASS_PALADIN,
+ 2, 250, DT_PHYSICAL, SA_NONE, 150, 0, MONSTER_HUMANOID,
+ 50, 50, 50, 50, 50, 10, 0, 0, 100, 0, 6, 0, 30, 0, 0,
+ 141, "knight"));
+ push_back(MonsterStruct("Lava Dweller", 500000, 1500, 30, 40, 1, CLASS_15, 5,
+ 100, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 100, 0,
+ 100, 50, 0, 50, 0, 0, 0, 0, 0, 19, 0, 0, 110, "fire"));
+ push_back(MonsterStruct("Lava Roach", 50000, 500, 20, 70, 1, CLASS_16, 5, 50,
+ DT_FIRE, SA_NONE, 1, 0, MONSTER_INSECT, 100, 100, 0,
+ 100, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 131, "Phantom"));
+ push_back(MonsterStruct("Power Lich", 200000, 500, 20, 60, 1, CLASS_15, 10, 10,
+ DT_1, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0,
+ 0, 80, 70, 0, 0, 0, 0, 1, 34, 0, 0, 141, "lich"));
+ push_back(MonsterStruct("Mystic Mage", 100000, 200, 20, 70, 1, CLASS_15, 10,
+ 20, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100,
+ 50, 50, 50, 30, 0, 0, 0, 50, 0, 1, 35, 0, 0, 163,
+ "monsterb"));
+ push_back(MonsterStruct("Magic Mage", 200000, 300, 25, 80, 1, CLASS_15, 10, 30,
+ DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, 50,
+ 50, 50, 50, 0, 0, 0, 75, 0, 1, 35, 0, 0, 163,
+ "monsterb"));
+ push_back(MonsterStruct("Minotaur", 250000, 3000, 80, 120, 1, CLASS_16, 100, 4,
+ DT_PHYSICAL, SA_AGING, 150, 0, MONSTER_0, 0, 0, 10, 0,
+ 0, 50, 60, 0, 0, 0, 0, 0, 37, 0, 0, 141, "stonegol"));
+ push_back(MonsterStruct("Gorgon", 250000, 4000, 90, 100, 1, CLASS_16, 100, 3,
+ DT_PHYSICAL, SA_STONE, 100, 0, MONSTER_0, 0, 0, 0, 0,
+ 0, 60, 70, 0, 0, 0, 0, 0, 37, 0, 0, 141, "stonegol"));
+ push_back(MonsterStruct("Higher Mummy", 100000, 400, 20, 60, 1, CLASS_CLERIC,
+ 10, 40, DT_PHYSICAL, SA_CURSEITEM, 100, 0,
+ MONSTER_UNDEAD, 0, 50, 50, 100, 50, 20, 75, 0, 0, 0, 0,
+ 0, 39, 0, 0, 141, "mummy"));
+ push_back(MonsterStruct("Orc Guard", 5000, 60, 10, 20, 1, CLASS_12, 3, 10,
+ DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0,
+ 0, 0, 0, 0, 0, 0, 50, 0, 2, 0, 40, 0, 0, 125, "orc"));
+ push_back(MonsterStruct("Octopod", 250000, 2500, 40, 80, 1, CLASS_15, 2, 100,
+ DT_POISON, SA_POISON, 1, 0, MONSTER_ANIMAL, 0, 0, 50,
+ 100, 0, 0, 0, 0, 0, 0, 0, 1, 41, 0, 0, 101, "photon"));
+ push_back(MonsterStruct("Ogre", 10000, 100, 15, 30, 1, CLASS_16, 4, 10,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 100, 0, 0, 0, 42, 0, 0, 136, "ogre"));
+ push_back(MonsterStruct("Orc Shaman", 10000, 50, 15, 30, 1, CLASS_15, 5, 5,
+ DT_COLD, SA_SLEEP, 1, 1, MONSTER_HUMANOID, 0, 0, 0, 0,
+ 0, 10, 0, 0, 75, 10, 2, 0, 43, 0, 0, 125, "fx7"));
+ push_back(MonsterStruct("Sabertooth", 10000, 100, 20, 60, 3, CLASS_16, 5, 10,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_ANIMAL, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 101, "saber"));
+ push_back(MonsterStruct("Sand Flower", 10000, 100, 10, 50, 5, CLASS_16, 5, 5,
+ DT_PHYSICAL, SA_INLOVE, 50, 0, MONSTER_0, 0, 0, 0, 0,
+ 0, 50, 50, 0, 0, 0, 0, 0, 45, 0, 0, 106, "sand"));
+ push_back(MonsterStruct("Killer Cobra", 25000, 1000, 25, 100, 1, CLASS_16, 2,
+ 100, DT_PHYSICAL, SA_AGING, 30, 0, MONSTER_ANIMAL, 0,
+ 0, 0, 100, 0, 50, 0, 0, 0, 0, 0, 0, 46, 0, 0, 100,
+ "hiss"));
+ push_back(MonsterStruct("Sewer Rat", 2000, 40, 5, 35, 1, CLASS_16, 3, 10,
+ DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 136, "rat"));
+ push_back(MonsterStruct("Sewer Slug", 1000, 25, 2, 25, 1, CLASS_16, 2, 10,
+ DT_PHYSICAL, SA_NONE, 5, 0, MONSTER_INSECT, 0, 0, 0,
+ 100, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 111, "zombie"));
+ push_back(MonsterStruct("Skeletal Lich", 500000, 2000, 30, 200, 1,
+ CLASS_SORCERER, 1000, 1, DT_ENERGY, SA_ERADICATE, 1, 1,
+ MONSTER_UNDEAD, 80, 70, 80, 100, 100, 50, 50, 0, 0, 0,
+ 0, 0, 49, 0, 0, 140, "elecbolt"));
+ push_back(MonsterStruct("Enchantress", 40000, 100, 25, 60, 1, CLASS_CLERIC, 3,
+ 150, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID,
+ 10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, 0, 50, 0, 0,
+ 163, "disint"));
+ push_back(MonsterStruct("Sorceress", 80000, 200, 30, 80, 1, CLASS_15, 2, 50,
+ DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10,
+ 10, 80, 0, 0, 0, 50, 5, 0, 50, 0, 0, 163, "disint"));
+ push_back(MonsterStruct("Arachnoid", 4000, 50, 10, 40, 1, CLASS_16, 3, 5,
+ DT_POISON, SA_POISON, 1, 0, MONSTER_INSECT, 0, 0, 0,
+ 100, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 104, "web"));
+ push_back(MonsterStruct("Medusa Sprite", 5000, 30, 5, 30, 1, CLASS_RANGER, 3,
+ 3, DT_PHYSICAL, SA_STONE, 10, 0, MONSTER_0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 53, 0, 0, 42, "hiss"));
+ push_back(MonsterStruct("Rogue", 5000, 50, 10, 30, 1, CLASS_ROBBER, 1, 60,
+ DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_HUMANOID, 0, 0,
+ 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 54, 0, 0, 100, "thief"));
+ push_back(MonsterStruct("Thief", 10000, 100, 15, 40, 1, CLASS_ROBBER, 1, 100,
+ DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0,
+ 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 54, 0, 0, 100,
+ "thief"));
+ push_back(MonsterStruct("Troll Grunt", 10000, 100, 5, 50, 1, CLASS_16, 2, 25,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50,
+ 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 136, "troll"));
+ push_back(MonsterStruct("Vampire", 200000, 400, 30, 80, 1, CLASS_CLERIC, 10,
+ 10, DT_PHYSICAL, SA_WEAKEN, 100, 0, MONSTER_UNDEAD, 50,
+ 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 57, 0, 0, 42,
+ "vamp"));
+ push_back(MonsterStruct("Vampire Lord", 300000, 500, 35, 100, 1, CLASS_CLERIC,
+ 10, 30, DT_PHYSICAL, SA_SLEEP, 120, 0, MONSTER_UNDEAD,
+ 50, 50, 50, 50, 50, 50, 70, 0, 0, 0, 0, 0, 58, 0, 0,
+ 42, "vamp"));
+ push_back(MonsterStruct("Vulture Roc", 200000, 2500, 50, 150, 1, CLASS_16, 5,
+ 60, DT_PHYSICAL, SA_NONE, 100, 0, MONSTER_ANIMAL, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 59, 0, 0, 120, "vulture"));
+ push_back(MonsterStruct("Sewer Hag", 50000, 75, 10, 40, 1, CLASS_PALADIN, 10,
+ 25, DT_ELECTRICAL, SA_INSANE, 1, 1, MONSTER_HUMANOID,
+ 0, 100, 0, 100, 0, 20, 0, 0, 0, 10, 0, 0, 62, 0, 0,
+ 108, "elecspel"));
+ push_back(MonsterStruct("Tidal Terror", 500000, 1000, 10, 200, 1, CLASS_15, 5,
+ 100, DT_COLD, SA_NONE, 1, 0, MONSTER_0, 100, 50, 50,
+ 100, 50, 0, 100, 0, 0, 0, 0, 1, 61, 0, 0, 101,
+ "splash3"));
+ push_back(MonsterStruct("Witch", 80000, 150, 15, 70, 1, CLASS_15, 10, 10,
+ DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 0, 100,
+ 0, 20, 0, 20, 0, 0, 0, 10, 0, 0, 63, 0, 0, 114,
+ "elecspel"));
+ push_back(MonsterStruct("Coven Leader", 120000, 250, 20, 100, 1, CLASS_15, 10,
+ 15, DT_ENERGY, SA_DRAINSP, 1, 1, MONSTER_HUMANOID, 10,
+ 100, 0, 50, 100, 50, 0, 0, 0, 20, 6, 0, 63, 0, 10, 114,
+ "elecspel"));
+ push_back(MonsterStruct("Master Wizard", 120000, 500, 25, 150, 2, CLASS_KNIGHT,
+ 10, 40, DT_FIRE, SA_NONE, 1, 1, MONSTER_HUMANOID, 100,
+ 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, 0, 64, 0, 0, 163,
+ "boltelec"));
+ push_back(MonsterStruct("Wizard", 60000, 250, 20, 125, 1, CLASS_PALADIN, 10,
+ 25, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30,
+ 30, 30, 30, 0, 0, 0, 20, 0, 0, 65, 0, 0, 163, "wizard"));
+ push_back(MonsterStruct("Dark Wolf", 10000, 70, 10, 70, 3, CLASS_16, 3, 8,
+ DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 1, 0, 100, "wolf"));
+ push_back(MonsterStruct("Screamer", 500000, 3000, 50, 200, 1, CLASS_15, 10, 20,
+ DT_POISON, SA_POISON, 1, 0, MONSTER_0, 0, 0, 0, 100, 0,
+ 0, 60, 0, 0, 0, 0, 0, 67, 0, 0, 110, "dragon"));
+ push_back(MonsterStruct("Cult Leader", 100000, 100, 20, 60, 1, CLASS_15, 10,
+ 10, DT_ENERGY, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 50,
+ 50, 50, 100, 50, 0, 0, 0, 100, 6, 0, 8, 0, 0, 100,
+ "cleric"));
+ push_back(MonsterStruct("Mega Dragon", 100000000, 64000, 100, 200, 1, CLASS_15,
+ 10, 200, DT_ENERGY, SA_ERADICATE, 1, 1, MONSTER_DRAGON,
+ 100, 100, 100, 100, 100, 100, 90, 0, 0, 232, 0, 0, 11,
+ 0, 7, 100, "tiger1"));
+ push_back(MonsterStruct("Gettlewaithe", 5000, 100, 15, 35, 2, CLASS_16, 5, 5,
+ DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2000, 0, 5, 0, 25, 0, 0, 100, "gremlin"));
+ push_back(MonsterStruct("Doom Knight", 500000, 1000, 50, 100, 4, CLASS_PALADIN,
+ 2, 250, DT_PHYSICAL, SA_DEATH, 150, 0,
+ MONSTER_HUMANOID, 80, 80, 80, 80, 80, 20, 0, 0, 200,
+ 0, 7, 0, 30, 0, 10, 100, "knight"));
+ push_back(MonsterStruct("Sandro", 200000, 1000, 20, 75, 1, CLASS_15, 10, 10,
+ DT_1, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0,
+ 90, 80, 0, 0, 100, 7, 1, 34, 0, 10, 100, "lich"));
+ push_back(MonsterStruct("Mega Mage", 500000, 500, 35, 100, 1, CLASS_15, 10, 40,
+ DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 80, 100, 80,
+ 80, 80, 80, 0, 0, 0, 100, 6, 1, 35, 0, 11, 100,
+ "monsterb"));
+ push_back(MonsterStruct("Orc Elite", 15000, 200, 15, 40, 2, CLASS_12, 5, 10,
+ DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_HUMANOID, 0, 0,
+ 0, 0, 0, 0, 0, 0, 100, 0, 3, 0, 40, 0, 0, 100, "orc"));
+ push_back(MonsterStruct("Shaalth", 20000, 300, 15, 50, 1, CLASS_15, 5, 10,
+ DT_COLD, SA_SLEEP, 1, 0, MONSTER_HUMANOID, 0, 0, 0, 0,
+ 0, 20, 0, 0, 1000, 50, 5, 0, 43, 0, 10, 100, "fx7"));
+ push_back(MonsterStruct("Rooka", 5000, 60, 5, 40, 1, CLASS_16, 3, 10,
+ DT_PHYSICAL, SA_DISEASE, 15, 0, MONSTER_ANIMAL, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10, 4, 0, 47, 0, 0, 100, "rat"));
+ push_back(MonsterStruct("Morgana", 200000, 300, 35, 100, 1, CLASS_15, 2, 60,
+ DT_ENERGY, SA_PARALYZE, 1, 1, MONSTER_HUMANOID, 50, 50,
+ 50, 50, 100, 80, 0, 0, 0, 100, 6, 0, 50, 0, 10, 100,
+ "disint"));
+ push_back(MonsterStruct("Master Thief", 20000, 100, 20, 50, 1, CLASS_ROBBER, 1,
+ 250, DT_PHYSICAL, SA_NONE, 40, 0, MONSTER_HUMANOID, 0,
+ 0, 0, 0, 0, 0, 0, 0, 250, 20, 4, 0, 54, 0, 14, 100,
+ "thief"));
+ push_back(MonsterStruct("Royal Vampire", 400000, 750, 40, 125, 1, CLASS_CLERIC,
+ 10, 50, DT_PHYSICAL, SA_CURSEITEM, 120, 0,
+ MONSTER_UNDEAD, 50, 50, 50, 50, 50, 50, 65, 0, 0, 0, 0,
+ 0, 57, 0, 0, 100, "vamp"));
+ push_back(MonsterStruct("Ct. Blackfang", 2000000, 1500, 50, 150, 1,
+ CLASS_CLERIC, 10, 100, DT_PHYSICAL, SA_DEATH, 120, 0,
+ MONSTER_UNDEAD, 75, 75, 75, 75, 75, 75, 75, 0, 0, 0, 0,
+ 0, 58, 0, 10, 100, "vamp"));
+ push_back(MonsterStruct("Troll Guard", 15000, 200, 10, 60, 1, CLASS_16, 2, 35,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50,
+ 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 100, "troll"));
+ push_back(MonsterStruct("Troll Chief", 20000, 300, 15, 65, 1, CLASS_16, 2, 50,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50,
+ 50, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 100, "troll"));
+ push_back(MonsterStruct("Hobstadt", 25000, 400, 20, 70, 1, CLASS_16, 2, 50,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 50, 50, 50,
+ 50, 0, 0, 0, 0, 1000, 0, 4, 0, 56, 0, 0, 100, "troll"));
+ push_back(MonsterStruct("Graalg", 20000, 200, 15, 50, 1, CLASS_16, 5, 10,
+ DT_PHYSICAL, SA_NONE, 30, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1000, 0, 5, 0, 42, 0, 0, 100, "ogre"));
+ push_back(MonsterStruct("Vampire King", 3000000, 10000, 60, 200, 1,
+ CLASS_CLERIC, 10, 250, DT_PHYSICAL, SA_ERADICATE, 150,
+ 0, MONSTER_UNDEAD, 80, 80, 80, 80, 80, 80, 90, 0, 0, 0,
+ 0, 0, 58, 0, 0, 100, "vamp"));
+ push_back(MonsterStruct("Valio", 60000, 150, 15, 60, 1, CLASS_PALADIN, 10, 25,
+ DT_1, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30,
+ 40, 30, 0, 0, 0, 0, 0, 0, 65, 0, 0, 100, "wizard"));
+ push_back(MonsterStruct("Sky Golem", 200000, 1000, 50, 100, 1, CLASS_15, 2,
+ 100, DT_COLD, SA_NONE, 1, 1, MONSTER_GOLEM, 50, 50,
+ 100, 50, 50, 50, 50, 0, 0, 0, 0, 1, 24, 0, 0, 100,
+ "golem"));
+ push_back(MonsterStruct("Gurodel", 100000, 750, 30, 60, 2, CLASS_16, 100, 6,
+ DT_PHYSICAL, SA_UNCONSCIOUS, 110, 0, MONSTER_0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5000, 0, 6, 0, 22, 0, 0, 100,
+ "giant"));
+ push_back(MonsterStruct("Yog", 25000, 100, 5, 60, 1, CLASS_SORCERER, 1, 30,
+ DT_PHYSICAL, SA_NONE, 25, 0, MONSTER_HUMANOID, 0, 0,
+ 0, 0, 0, 0, 0, 0, 200, 0, 4, 0, 6, 0, 10, 100,
+ "barbarch"));
+ push_back(MonsterStruct("Sharla", 10000, 50, 5, 50, 1, CLASS_RANGER, 3, 4,
+ DT_PHYSICAL, SA_NONE, 20, 0, MONSTER_0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 53, 0, 0, 100, "hiss"));
+ push_back(MonsterStruct("Ghost Mummy", 500000, 500, 35, 175, 1, CLASS_CLERIC,
+ 200, 5, DT_PHYSICAL, SA_AGING, 150, 0, MONSTER_UNDEAD,
+ 0, 60, 80, 80, 80, 50, 80, 0, 0, 0, 0, 0, 40, 0, 6,
+ 100, "orc"));
+ push_back(MonsterStruct("Phase Mummy", 500000, 500, 35, 175, 1, CLASS_CLERIC,
+ 200, 6, DT_PHYSICAL, SA_DRAINSP, 150, 0,
+ MONSTER_UNDEAD, 0, 70, 80, 80, 80, 60, 85, 0, 0, 0, 0,
+ 0, 39, 0, 7, 100, "mummy"));
+ push_back(MonsterStruct("Xenoc", 250000, 700, 35, 175, 1, CLASS_15, 10, 50,
+ DT_ENERGY, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 50, 50,
+ 50, 100, 50, 0, 0, 0, 100, 6, 0, 64, 0, 0, 100,
+ "boltelec"));
+ push_back(MonsterStruct("Barkman", 4000000, 40000, 25, 100, 3, CLASS_16, 250,
+ 1, DT_FIRE, SA_NONE, 1, 0, MONSTER_0, 100, 50, 0, 100,
+ 0, 0, 0, 0, 0, 0, 6, 0, 19, 0, 11, 100, "fire"));
+}
+
+void MonsterData::load(const Common::String &name) {
+ File f(name);
+ synchronize(f);
+}
+
+void MonsterData::synchronize(Common::SeekableReadStream &s) {
+ clear();
+
+ MonsterData spr;
+ while (!s.eos()) {
+ spr.synchronize(s);
+ push_back(spr);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+SurroundingMazes::SurroundingMazes() {
+ _north = 0;
+ _east = 0;
+ _south = 0;
+ _west = 0;
+}
+
+void SurroundingMazes::synchronize(Common::SeekableReadStream &s) {
+ _north = s.readUint16LE();
+ _east = s.readUint16LE();
+ _south = s.readUint16LE();
+ _west = s.readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
+MazeDifficulties::MazeDifficulties() {
+ _unlockDoor = 0;
+ _unlockBox = 0;
+ _bashDoor = 0;
+ _bashGrate = 0;
+ _bashWall = 0;
+}
+
+void MazeDifficulties::synchronize(Common::SeekableReadStream &s) {
+ _wallNoPass = s.readByte();
+ _surfaceNoPass = s.readByte();
+ _unlockDoor = s.readByte();
+ _unlockBox = s.readByte();
+ _bashDoor = s.readByte();
+ _bashGrate = s.readByte();
+ _bashWall = s.readByte();
+ _chance2Run = s.readByte();
+}
+
+/*------------------------------------------------------------------------*/
+
+MazeData::MazeData() {
+ for (int y = 0; y < MAP_HEIGHT; ++y) {
+ Common::fill(&_wallData[y][0], &_wallData[y][MAP_WIDTH], 0);
+ Common::fill(&_cellFlag[y][0], &_cellFlag[y][MAP_WIDTH], 0);
+ Common::fill(&_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH], 0);
+ Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], 0);
+ _wallTypes[y] = 0;
+ _surfaceTypes[y] = 0;
+ }
+ _mazeNumber = 0;
+ _mazeFlags = _mazeFlags2 = 0;
+ _floorType = 0;
+ _trapDamage = 0;
+ _wallKind = 0;
+ _tavernTips = 0;
+}
+
+void MazeData::synchronize(Common::SeekableReadStream &s) {
+ for (int y = 0; y < MAP_HEIGHT; ++y) {
+ for (int x = 0; x < MAP_WIDTH; ++x)
+ _wallData[y][x] = s.readUint16LE();
+ }
+ for (int y = 0; y < MAP_HEIGHT; ++y) {
+ for (int x = 0; x < MAP_WIDTH; ++x)
+ _cellFlag[y][x] = s.readByte();
+ }
+
+ _mazeNumber = s.readUint16LE();
+ _surroundingMazes.synchronize(s);
+ _mazeFlags = s.readUint16LE();
+ _mazeFlags2 = s.readUint16LE();
+
+ for (int i = 0; i < 16; ++i)
+ _wallTypes[i] = s.readByte();
+ for (int i = 0; i < 16; ++i)
+ _surfaceTypes[i] = s.readByte();
+
+ _floorType = s.readByte();
+ _runPosition.x = s.readByte();
+ _difficulties.synchronize(s);
+ _runPosition.y = s.readByte();
+ _trapDamage = s.readByte();
+ _wallKind = s.readByte();
+ _tavernTips = s.readByte();
+
+ Common::Serializer ser(&s, nullptr);
+ for (int y = 0; y < MAP_HEIGHT; ++y)
+ SavesManager::syncBitFlags(ser, &_seenTiles[y][0], &_seenTiles[y][MAP_WIDTH]);
+ for (int y = 0; y < MAP_HEIGHT; ++y)
+ SavesManager::syncBitFlags(ser, &_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH]);
+}
+
+/**
+ * Flags all tiles for the map as having been stepped on
+ */
+void MazeData::setAllTilesStepped() {
+ for (int y = 0; y < MAP_HEIGHT; ++y)
+ Common::fill(&_steppedOnTiles[y][0], &_steppedOnTiles[y][MAP_WIDTH], true);
+}
+
+void MazeData::clearCellBits() {
+ for (int y = 0; y < MAP_HEIGHT; ++y) {
+ for (int x = 0; x < MAP_WIDTH; ++x)
+ _cellFlag[y][x] &= 0xF8;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+MobStruct::MobStruct() {
+ _id = 0;
+ _direction = DIR_NORTH;
+}
+
+bool MobStruct::synchronize(Common::SeekableReadStream &s) {
+ _pos.x = (int8)s.readByte();
+ _pos.y = (int8)s.readByte();
+ _id = s.readByte();
+ _direction = (Direction)s.readByte();
+
+ return _id != 0xff || _pos.x != -1 || _pos.y != -1;
+}
+
+/*------------------------------------------------------------------------*/
+
+MonsterObjectData::MonsterObjectData(XeenEngine *vm): _vm(vm) {
+}
+
+void MonsterObjectData::synchronize(Common::SeekableReadStream &s,
+ bool isOutdoors, MonsterData monsterData) {
+ _objects.clear();
+ _monsters.clear();
+ _wallPicIds.clear();
+ _wallImages.clear();
+ Common::Array<int> objectSprites;
+ Common::Array<int> monsterIds;
+ Common::Array<MobStruct> objData;
+ Common::Array<MobStruct> monData;
+ byte b;
+
+ for (int i = 0; i < 16; ++i) {
+ if ((b = s.readByte()) != 0xff)
+ objectSprites.push_back(b);
+ }
+ for (int i = 0; i < 16; ++i) {
+ if ((b = s.readByte()) != 0xff)
+ monsterIds.push_back(b);
+ }
+ for (int i = 0; i < 16; ++i) {
+ if ((b = s.readByte()) != 0xff)
+ _wallPicIds.push_back(b);
+ }
+
+ MobStruct mobStruct;
+ while (mobStruct.synchronize(s))
+ objData.push_back(mobStruct);
+ while (mobStruct.synchronize(s))
+ monData.push_back(mobStruct);
+ if (!isOutdoors) {
+ while (mobStruct.synchronize(s))
+ _wallImages.push_back(mobStruct);
+ }
+
+ // Merge up objects
+ _objects.resize(objData.size());
+ for (uint i = 0; i < objData.size(); ++i) {
+ MazeObject &dest = _objects[i];
+ dest._position = objData[i]._pos;
+ dest._number = objData[i]._id;
+ dest._id = objectSprites[dest._number];
+ dest._direction = objData[i]._direction;
+ dest._frame = 100;
+ }
+
+ // merge up monsters
+ for (uint i = 0; i < monData.size(); ++i) {
+ MazeMonster &dest = _monsters[i];
+ dest._position = monData[i]._pos;
+ dest._id = monData[i]._id;
+ dest._refId = monsterIds[dest._id];
+
+ MonsterStruct &mon = monsterData[dest._refId];
+ dest._hp = mon._hp;
+ dest._frame = _vm->getRandomNumber(7);
+ dest._effect1 = dest._effect2 = mon._animationEffect;
+ if (mon._animationEffect)
+ dest._effect3 = _vm->getRandomNumber(7);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+HeadData::HeadData() {
+ for (int y = 0; y < MAP_HEIGHT; ++y) {
+ for (int x = 0; x < MAP_WIDTH; ++x) {
+ _data[y][x]._left = _data[y][x]._right = 0;
+ }
+ }
+}
+
+void HeadData::synchronize(Common::SeekableReadStream &s) {
+ for (int y = 0; y < MAP_HEIGHT; ++y) {
+ for (int x = 0; x < MAP_WIDTH; ++x) {
+ _data[y][x]._left = s.readByte();
+ _data[y][x]._right = s.readByte();
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
+ _townPortalSide = 0;
+ _sideObj = 0;
+ _sideMon = 0;
+ _isOutdoors = false;
+}
+
+void Map::load(int mapId) {
+ Screen &screen = *_vm->_screen;
+ if (_vm->_falling) {
+ Window &w = screen._windows[9];
+ w.open();
+ w.writeString(OOPS);
+ } else {
+ PleaseWait::show(_vm);
+ }
+
+ if (mapId >= 113 && mapId <= 127) {
+ _townPortalSide = 0;
+ } else {
+ _townPortalSide = _vm->_loadDarkSide;
+ }
+
+ if (_vm->getGameID() == GType_WorldOfXeen) {
+ if (_vm->_loadDarkSide) {
+ _objPicSprites.load("clouds.dat");
+ _monsterData.load("xeen.mon");
+ _wallPicSprites.load("xeenpic.dat");
+ } else {
+ switch (mapId) {
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 128:
+ _objPicSprites.load("clouds.dat");
+ _monsterData.load("dark.mon");
+ _wallPicSprites.load("darkpic.dat");
+ _sideObj = 0;
+ break;
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 124:
+ _objPicSprites.load("clouds.dat");
+ _monsterData.load("xeen.mon");
+ _wallPicSprites.load("darkpic.dat");
+ _sideObj = 0;
+ _sideMon = 0;
+ break;
+ case 125:
+ case 126:
+ case 127:
+ _objPicSprites.load("clouds.dat");
+ _monsterData.load("dark.mon");
+ _wallPicSprites.load("xeenpic.dat");
+ break;
+ default:
+ _objPicSprites.load("dark.dat");
+ _monsterData.load("ddark.mon");
+ _wallPicSprites.load("darkpic.dat");
+ break;
+ }
+ }
+ }
+
+ bool isDarkCc = _vm->getGameID() == GType_DarkSide;
+ uint16 mapGrid[9];
+ uint16 *gridPtr = &mapGrid[0];
+ bool textLoaded = false;
+
+ // Iterate through loading the given maze as well as the two successive
+ // mazes in each of the four cardinal directions
+ for (int idx = 0; idx < 9; ++idx, ++gridPtr) {
+ if (mapId != 0) {
+ // Load in the maze's data file
+ Common::String datName = Common::String::format("maze%c%03u.dat",
+ (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+ File datFile(datName);
+ _mazeData.synchronize(datFile);
+ datFile.close();
+
+ if (isDarkCc && mapId == 50)
+ _mazeData.setAllTilesStepped();
+ if (!isDarkCc && _vm->_party._gameFlags[25] &&
+ (mapId == 42 || mapId == 43 || mapId == 4)) {
+ _mazeData.clearCellBits();
+ }
+
+ _isOutdoors = (_mazeData._mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
+
+ // Handle loading text data
+ if (!textLoaded) {
+ textLoaded = true;
+ Common::String txtName = Common::String::format("%s%c%03u.txt",
+ isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0');
+ File fText(txtName);
+ char mazeName[33];
+ fText.read(mazeName, 33);
+ mazeName[32] = '\0';
+
+ _mazeName = Common::String(mazeName);
+ fText.close();
+
+ // Load the monster data
+ Common::String mobName = Common::String::format("maze%c%03u.mob",
+ (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+ File mobFile(mobName);
+ _mobData.synchronize(mobFile, _isOutdoors, _monsterData);
+ mobFile.close();
+
+ Common::String headName = Common::String::format("aaze%c%03u.hed",
+ (_vm->_party._mazeId >= 100) ? 'x' : '0', _vm->_party._mazeId);
+ File headFile(headName);
+ _headData.synchronize(headFile);
+ headFile.close();
+
+ if (!isDarkCc && _vm->_party._mazeId)
+ _mobData._monsters.clear();
+
+ if (!isDarkCc && mapId == 15) {
+ if ((_mobData._monsters[0]._position.x > 31 || _mobData._monsters[0]._position.y > 31) &&
+ (_mobData._monsters[1]._position.x > 31 || _mobData._monsters[1]._position.y > 31) &&
+ (_mobData._monsters[2]._position.x > 31 || _mobData._monsters[2]._position.y > 31)) {
+ _vm->_party._gameFlags[56] = true;
+ }
+ }
+ }
+ }
+
+ // TODO: Move to next surrounding maze
+ }
+
+ // TODO
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
new file mode 100644
index 0000000000..4482173642
--- /dev/null
+++ b/engines/xeen/map.h
@@ -0,0 +1,264 @@
+/* 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.
+ *
+ */
+
+#ifndef XEEN_MAP_H
+#define XEEN_MAP_H
+
+#include "common/stream.h"
+#include "common/rect.h"
+#include "xeen/party.h"
+#include "xeen/sprites.h"
+
+namespace Xeen {
+
+#define MAP_WIDTH 16
+#define MAP_HEIGHT 16
+
+class XeenEngine;
+
+enum DamageType {
+ DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3,
+ DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7,
+ DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10,
+ DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13,
+ DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16,
+ DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18
+};
+
+enum SpecialAttack {
+ SA_NONE = 0, SA_MAGIC = 1, SA_FIRE = 2, SA_ELEC = 3, SA_COLD = 4,
+ SA_POISON = 5, SA_ENERGY = 6, SA_DISEASE = 7, SA_INSANE = 8,
+ SA_SLEEP = 9, SA_CURSEITEM = 10, SA_INLOVE = 11, SA_DRAINSP = 12,
+ SA_CURSE = 13, SA_PARALYZE = 14, SA_UNCONSCIOUS = 15,
+ SA_CONFUSE = 16, SA_BREAKWEAPON = 17, SA_WEAKEN = 18,
+ SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22
+};
+
+enum MonsterType {
+ MONSTER_0 = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2,
+ MONSTER_HUMANOID = 3, MONSTER_UNDEAD = 4, MONSTER_GOLEM = 5,
+ MONSTER_DRAGON = 6
+};
+
+class MonsterStruct {
+public:
+ Common::String _name;
+ int _experience;
+ int _hp;
+ int _accuracy;
+ int _speed;
+ int _numberOfAttacks;
+ CharacterClass _hatesClass;
+ int _strikes;
+ int _dmgPerStrike;
+ DamageType _attackType;
+ SpecialAttack _specialAttack;
+ int _hitChance;
+ int _rangeAttack;
+ MonsterType _monsterType;
+ int _fireResistence;
+ int _electricityResistence;
+ int _coldResistence;
+ int _poisonResistence;
+ int _energyResistence;
+ int _magicResistence;
+ int _phsyicalResistence;
+ int _field29;
+ int _gold;
+ int _gems;
+ int _itemDrop;
+ int _flying;
+ int _imageNumber;
+ int _loopAnimation;
+ int _animationEffect;
+ int _field32;
+ Common::String _attackVoc;
+public:
+ MonsterStruct();
+ MonsterStruct(Common::String name, int experience, int hp, int accuracy,
+ int speed, int numberOfAttacks, CharacterClass hatesClass, int strikes,
+ int dmgPerStrike, DamageType attackType, SpecialAttack specialAttack,
+ int hitChance, int rangeAttack, MonsterType monsterType,
+ int fireResistence, int electricityResistence, int coldResistence,
+ int poisonResistence, int energyResistence, int magicResistence,
+ int phsyicalResistence, int field29, int gold, int gems, int itemDrop,
+ int flying, int imageNumber, int loopAnimation, int animationEffect,
+ int field32, Common::String attackVoc);
+
+ void synchronize(Common::SeekableReadStream &s);
+};
+
+class MonsterData : public Common::Array<MonsterStruct> {
+private:
+ void synchronize(Common::SeekableReadStream &s);
+public:
+ MonsterData();
+
+ void load(const Common::String &name);
+};
+
+class SurroundingMazes {
+public:
+ int _north;
+ int _east;
+ int _south;
+ int _west;
+public:
+ SurroundingMazes();
+
+ void synchronize(Common::SeekableReadStream &s);
+};
+
+class MazeDifficulties {
+public:
+ int _wallNoPass;
+ int _surfaceNoPass;
+ int _unlockDoor;
+ int _unlockBox;
+ int _bashDoor;
+ int _bashGrate;
+ int _bashWall;
+ int _chance2Run;
+public:
+ MazeDifficulties();
+
+ void synchronize(Common::SeekableReadStream &s);
+};
+
+enum MazeFlags {
+ OUTFLAG_GRATE = 0x80, OUTFLAG_DRAIN = 0x20, OUTFLAG_OBJECT_EXISTS = 0x08,
+ INFLAG_INSIDE = 0x08,
+ FLAG_WATER = 0x40, FLAG_AUTOEXECUTE_EVENT = 0x10,
+ FLAG_GROUND_BITS = 7
+};
+
+enum MazeFlags2 { FLAG_IS_OUTDOORS = 0x8000, FLAG_IS_DARK = 0x4000 };
+
+class MazeData {
+public:
+ int _wallData[MAP_HEIGHT][MAP_WIDTH];
+ int _cellFlag[MAP_HEIGHT][MAP_WIDTH];
+ int _mazeNumber;
+ SurroundingMazes _surroundingMazes;
+ int _mazeFlags;
+ int _mazeFlags2;
+ int _wallTypes[16];
+ int _surfaceTypes[16];
+ int _floorType;
+ Common::Point _runPosition;
+ MazeDifficulties _difficulties;
+ int _trapDamage;
+ int _wallKind;
+ int _tavernTips;
+ bool _seenTiles[MAP_HEIGHT][MAP_WIDTH];
+ bool _steppedOnTiles[MAP_HEIGHT][MAP_WIDTH];
+public:
+ MazeData();
+
+ void synchronize(Common::SeekableReadStream &s);
+
+ void setAllTilesStepped();
+
+ void clearCellBits();
+};
+
+class MobStruct {
+public:
+ Common::Point _pos;
+ int _id;
+ Direction _direction;
+public:
+ MobStruct();
+
+ bool synchronize(Common::SeekableReadStream &s);
+};
+
+struct MazeObject {
+ Common::Point _position;
+ int _number;
+ int _frame;
+ int _id;
+ Direction _direction;
+ bool _flipped;
+};
+
+struct MazeMonster {
+ Common::Point _position;
+ int _frame;
+ int _id;
+ int _refId;
+ int _hp;
+ int _effect1, _effect2;
+ int _effect3;
+};
+
+class MonsterObjectData {
+private:
+ XeenEngine *_vm;
+public:
+ Common::Array<MazeObject> _objects;
+ Common::Array<MazeMonster> _monsters;
+ Common::Array<int> _wallPicIds;
+ Common::Array<MobStruct> _wallImages;
+public:
+ MonsterObjectData(XeenEngine *vm);
+
+ void synchronize(Common::SeekableReadStream &s, bool isOutdoors,
+ MonsterData monsterData);
+};
+
+class HeadData {
+public:
+ struct HeadEntry {
+ int _left;
+ int _right;
+ };
+ HeadEntry _data[MAP_HEIGHT][MAP_WIDTH];
+public:
+ HeadData();
+
+ void synchronize(Common::SeekableReadStream &s);
+};
+
+class Map {
+private:
+ XeenEngine *_vm;
+ MazeData _mazeData;
+ Common::String _mazeName;
+ MonsterObjectData _mobData;
+ HeadData _headData;
+ SpriteResource _objPicSprites;
+ MonsterData _monsterData;
+ SpriteResource _wallPicSprites;
+ int _townPortalSide;
+ int _sideObj;
+ int _sideMon;
+ bool _isOutdoors;
+public:
+ Map(XeenEngine *vm);
+
+ void load(int mapId);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_MAP_H */
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 7f0caf7b10..5cbb1bb064 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -7,12 +7,14 @@ MODULE_OBJS := \
debugger.o \
detection.o \
dialogs.o \
+ dialogs_error.o \
dialogs_options.o \
events.o \
files.o \
font.o \
interface.o \
items.o \
+ map.o \
party.o \
resdata.o \
resources.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 25366d52ed..ec25f4a71c 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -44,7 +44,7 @@ PlayerStruct::PlayerStruct() {
_sex = MALE;
_race = HUMAN;
_xeenSide = 0;
- _class = KNIGHT;
+ _class = CLASS_KNIGHT;
_ACTemp = 0;
_dbDay = 0;
_tempAge = 0;
@@ -302,7 +302,7 @@ void Party::synchronize(Common::Serializer &s) {
bool Party::checkSkill(Skill skillId) {
uint total = 0;
for (uint i = 0; i < _activeParty.size(); ++i) {
- if (_activeParty[i]->_skills[skillId]) {
+ if (_activeParty[i]._skills[skillId]) {
++total;
switch (skillId) {
@@ -324,6 +324,8 @@ bool Party::checkSkill(Skill skillId) {
}
}
}
+
+ return false;
}
bool Party::isInParty(int charId) {
@@ -335,4 +337,10 @@ bool Party::isInParty(int charId) {
return false;
}
+void Party::copyPartyToRoster(Roster &r) {
+ for (int i = 0; i < _partyCount; ++i) {
+ r[_partyMembers[i]] = _activeParty[i];
+ }
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 7e5010427f..b415707344 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -39,8 +39,11 @@ enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
-enum CharacterClass { KNIGHT = 0, PALADIN = 1, ARCHER = 2, CLERIC = 3,
- SORCERER = 4, ROBBER = 5, NINJA = 6, BARBARIAN = 7, DRUID = 8, RANGER = 9
+enum CharacterClass {
+ CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3,
+ CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7,
+ CLASS_DRUID = 8, CLASS_RANGER = 9,
+ CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16
};
enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3,
@@ -195,7 +198,7 @@ public:
bool _characterFlags[30][24];
public:
// Other party related runtime data
- Common::Array<PlayerStruct *> _activeParty;
+ Common::Array<PlayerStruct> _activeParty;
int _combatPartyCount;
public:
Party();
@@ -205,6 +208,8 @@ public:
bool checkSkill(Skill skillId);
bool isInParty(int charId);
+
+ void copyPartyToRoster(Roster &r);
};
} // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 79e8ba183c..3f59f3e1c9 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -279,4 +279,28 @@ const int CHAR_FACES_X[6] = { 10, 45, 81, 117, 153, 189 };
const int HP_BARS_X[6] = { 13, 50, 86, 122, 158, 194 };
+const char *const NO_ONE_TO_ADVENTURE_WITH = "You have no one to adventure with";
+
+const char *const YOUR_ROSTER_IS_FULL = "Your Roster is full!";
+
+const byte BACKGROUND_XLAT[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF7, 0xFF, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF9, 0xFF, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF7, 0xFF, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF5, 0xFF, 0x0B, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF3, 0xFF, 0x0D, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+};
+
+const char *const PLEASE_WAIT = "\014""d\003""c\011""000"
+ "\013""002Please Wait...";
+
+const char *const OOPS = "\003""c\011""000\013""002Oops...";
+
} // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 80febec9b4..78104b233c 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -58,6 +58,16 @@ extern const int CHAR_FACES_X[6];
extern const int HP_BARS_X[6];
+extern const char *const NO_ONE_TO_ADVENTURE_WITH;
+
+extern const byte BACKGROUND_XLAT[];
+
+extern const char *const YOUR_ROSTER_IS_FULL;
+
+extern const char *const PLEASE_WAIT;
+
+extern const char *const OOPS;
+
} // End of namespace Xeen
#endif /* XEEN_RESOURCES_H */
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 7482a12ff5..95957c4daa 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -75,4 +75,12 @@ void SavesManager::reset() {
delete pty;
}
+void SavesManager::readCharFile() {
+ warning("TODO: readCharFile");
+}
+
+void SavesManager::writeCharFile() {
+ warning("TODO: writeCharFile");
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index f3ace80a03..1e67638fe4 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -49,6 +49,10 @@ public:
public:
SavesManager(XeenEngine *vm, Party &party, Roster &roster);
void reset();
+
+ void readCharFile();
+
+ void writeCharFile();
};
} // End of namespace Xeen
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index ba2c97b267..cfde7804ae 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -166,10 +166,10 @@ void Window::writeString(const Common::String &s) {
_vm->_screen->writeString(s, _innerBounds);
}
-void Window::drawList(DrawStruct *items) {
+void Window::drawList(DrawStruct *items, int count) {
Screen &screen = *_vm->_screen;
- for (; items->_sprites != nullptr; ++items) {
+ for (int i = 0; i < count; ++i, ++items) {
if (items->_frame == -1 || items->_scale == -1)
continue;
diff --git a/engines/xeen/screen.h b/engines/xeen/screen.h
index ae38ec3a03..1e164a3166 100644
--- a/engines/xeen/screen.h
+++ b/engines/xeen/screen.h
@@ -90,7 +90,7 @@ public:
void writeString(const Common::String &s);
- void drawList(DrawStruct *items);
+ void drawList(DrawStruct *items, int count);
};
class Screen: public FontSurface {
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 5b8fe5266a..598870dc57 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -39,6 +39,10 @@ SpriteResource::SpriteResource(const Common::String &filename) {
load(filename);
}
+SpriteResource::~SpriteResource() {
+ clear();
+}
+
void SpriteResource::load(const Common::String &filename) {
// Open the resource
File f(filename);
@@ -60,8 +64,10 @@ void SpriteResource::load(const Common::String &filename) {
}
}
-SpriteResource::~SpriteResource() {
+void SpriteResource::clear() {
delete[] _data;
+ _data = nullptr;
+ _filesize = 0;
}
void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Point &destPos) const {
diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h
index e9cdf721eb..998d5d3e79 100644
--- a/engines/xeen/sprites.h
+++ b/engines/xeen/sprites.h
@@ -51,6 +51,8 @@ public:
void load(const Common::String &filename);
+ void clear();
+
void draw(XSurface &dest, int frame, const Common::Point &destPos) const;
void draw(XSurface &dest, int frame) const;
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index 1574871c25..b3ac7433a3 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -38,7 +38,9 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
: Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") {
_debugger = nullptr;
_events = nullptr;
+ _files = nullptr;
_interface = nullptr;
+ _map = nullptr;
_saves = nullptr;
_screen = nullptr;
_sound = nullptr;
@@ -49,16 +51,19 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
_face1State = 0;
_face2State = 0;
_noDirectionSense = false;
+ _falling = false;
}
XeenEngine::~XeenEngine() {
delete _debugger;
delete _events;
delete _interface;
+ delete _map;
delete _saves;
delete _screen;
delete _sound;
delete _eventData;
+ delete _files;
}
void XeenEngine::initialize() {
@@ -69,10 +74,11 @@ void XeenEngine::initialize() {
DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling");
// Create sub-objects of the engine
- FileManager::init(this);
+ _files = new FileManager(this);
_debugger = new Debugger(this);
_events = new EventsManager(this);
_interface = new Interface(this);
+ _map = new Map(this);
_saves = new SavesManager(this, _party, _roster);
_screen = new Screen(this);
_screen->setupWindows();
@@ -249,9 +255,34 @@ void XeenEngine::showMainMenu() {
//OptionsMenu::show(this);
}
+/**
+ * Main method for playing the game
+ */
void XeenEngine::playGame() {
_saves->reset();
- _interface->setup(true);
+ play();
+}
+
+/*
+ * Secondary method for handling the actual gameplay
+ */
+void XeenEngine::play() {
+ // TODO: Init variables
+
+ _screen->loadBackground("back.raw");
+ _screen->loadPalette("mm4.pal");
+ _interface->loadCharIcons(_party._partyCount);
+ _iconsSprites.load("main.icn");
+
+ if (getGameID() != GType_WorldOfXeen && !_loadDarkSide) {
+ _loadDarkSide = true;
+ _party._mazeId = 29;
+ _party._mazeDirection = DIR_NORTH;
+ _party._mazePosition.x = 25;
+ _party._mazePosition.y = 21;
+ }
+
+ _map->load(_party._mazeId);
}
} // End of namespace Xeen
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index a7210ca871..9938519b9b 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -34,7 +34,9 @@
#include "xeen/debugger.h"
#include "xeen/dialogs.h"
#include "xeen/events.h"
+#include "xeen/files.h"
#include "xeen/interface.h"
+#include "xeen/map.h"
#include "xeen/party.h"
#include "xeen/saves.h"
#include "xeen/screen.h"
@@ -77,7 +79,8 @@ enum Mode {
MODE_6 = 6,
MODE_7 = 7,
MODE_8 = 8,
- MODE_9 = 9
+ MODE_9 = 9,
+ MODE_17 = 17
};
struct XeenGameDescription;
@@ -90,10 +93,15 @@ private:
const XeenGameDescription *_gameDescription;
Common::RandomSource _randomSource;
int _loadSaveSlot;
+ SpriteResource _iconsSprites;
void showIntro();
void showMainMenu();
+
+ void play();
+
+ void pleaseWait();
protected:
/**
* Play the game
@@ -119,7 +127,9 @@ private:
public:
Debugger *_debugger;
EventsManager *_events;
+ FileManager *_files;
Interface *_interface;
+ Map *_map;
SavesManager *_saves;
Screen *_screen;
SoundManager *_sound;
@@ -134,6 +144,7 @@ public:
int _face1State;
int _face2State;
bool _noDirectionSense;
+ bool _falling;
public:
XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
virtual ~XeenEngine();